From ce77eb7534eb86c856c643327a843180a9b7c465 Mon Sep 17 00:00:00 2001 From: hexxa Date: Sat, 3 Sep 2022 23:32:32 +0800 Subject: [PATCH] test(server): fix bugs and tests --- src/db/interface.go | 10 +- src/db/rdb/sqlite/files.go | 40 ++-- src/db/rdb/sqlite/files_sharings.go | 32 +++- src/db/rdb/sqlite/files_uploadings.go | 34 ++-- src/handlers/fileshdr/async_handlers.go | 2 +- src/handlers/fileshdr/handlers.go | 238 ++++++++++-------------- src/handlers/multiusers/handlers.go | 2 +- src/handlers/util.go | 6 +- src/server/config.go | 6 +- src/server/server.go | 45 +++-- src/server/server_files_test.go | 7 +- src/server/server_permission_test.go | 14 +- src/server/server_users_test.go | 118 ++++++------ 13 files changed, 266 insertions(+), 288 deletions(-) diff --git a/src/db/interface.go b/src/db/interface.go index 93c7dc7..8d51bbc 100644 --- a/src/db/interface.go +++ b/src/db/interface.go @@ -71,22 +71,22 @@ type IFilesFunctions interface { type IFileDB interface { AddFileInfo(ctx context.Context, userId uint64, itemPath string, info *FileInfo) error DelFileInfo(ctx context.Context, userId uint64, itemPath string) error - GetFileInfo(ctx context.Context, userId uint64, itemPath string) (*FileInfo, error) - SetSha1(ctx context.Context, userId uint64, itemPath, sign string) error - MoveFileInfos(ctx context.Context, userID uint64, oldPath, newPath string, isDir bool) error + GetFileInfo(ctx context.Context, itemPath string) (*FileInfo, error) + SetSha1(ctx context.Context, itemPath, sign string) error + MoveFileInfos(ctx context.Context, userId uint64, oldPath, newPath string, isDir bool) error ListFileInfos(ctx context.Context, itemPaths []string) (map[string]*FileInfo, error) } type IUploadDB interface { AddUploadInfos(ctx context.Context, userId uint64, tmpPath, filePath string, info *FileInfo) error DelUploadingInfos(ctx context.Context, userId uint64, realPath string) error - // MoveUploadingInfos(ctx context.Context, userId uint64, uploadPath, itemPath string) error + MoveUploadingInfos(ctx context.Context, userId uint64, uploadPath, itemPath string) error SetUploadInfo(ctx context.Context, user uint64, filePath string, newUploaded int64) error GetUploadInfo(ctx context.Context, userId uint64, filePath string) (string, int64, int64, error) ListUploadInfos(ctx context.Context, user uint64) ([]*UploadInfo, error) } type ISharingDB interface { - IsSharing(ctx context.Context, userId uint64, dirPath string) bool + IsSharing(ctx context.Context, userId uint64, dirPath string) (bool, error) GetSharingDir(ctx context.Context, hashID string) (string, error) AddSharing(ctx context.Context, userId uint64, dirPath string) error DelSharing(ctx context.Context, userId uint64, dirPath string) error diff --git a/src/db/rdb/sqlite/files.go b/src/db/rdb/sqlite/files.go index ff29ea3..2502690 100644 --- a/src/db/rdb/sqlite/files.go +++ b/src/db/rdb/sqlite/files.go @@ -23,7 +23,7 @@ var ( maxHashingTime = 10 ) -func (st *SQLiteStore) getFileInfo(ctx context.Context, userId uint64, itemPath string) (*db.FileInfo, error) { +func (st *SQLiteStore) getFileInfo(ctx context.Context, itemPath string) (*db.FileInfo, error) { var infoStr string fInfo := &db.FileInfo{} var isDir bool @@ -33,10 +33,8 @@ func (st *SQLiteStore) getFileInfo(ctx context.Context, userId uint64, itemPath ctx, `select is_dir, size, share_id, info from t_file_info - where path=? and user=? - `, + where path=?`, itemPath, - userId, ).Scan( &isDir, &size, @@ -61,11 +59,11 @@ func (st *SQLiteStore) getFileInfo(ctx context.Context, userId uint64, itemPath return fInfo, nil } -func (st *SQLiteStore) GetFileInfo(ctx context.Context, userId uint64, itemPath string) (*db.FileInfo, error) { +func (st *SQLiteStore) GetFileInfo(ctx context.Context, itemPath string) (*db.FileInfo, error) { st.RLock() defer st.RUnlock() - return st.getFileInfo(ctx, userId, itemPath) + return st.getFileInfo(ctx, itemPath) } func (st *SQLiteStore) ListFileInfos(ctx context.Context, itemPaths []string) (map[string]*db.FileInfo, error) { @@ -160,31 +158,22 @@ func (st *SQLiteStore) AddFileInfo(ctx context.Context, userId uint64, itemPath return st.setUsed(ctx, userId, true, info.Size) } -func (st *SQLiteStore) delFileInfo(ctx context.Context, userId uint64, itemPath string) error { +func (st *SQLiteStore) delFileInfo(ctx context.Context, itemPath string) error { _, err := st.db.ExecContext( ctx, `delete from t_file_info - where path=? and user=? + where path=? `, itemPath, - userId, ) return err } -// func (st *SQLiteStore) DelFileInfo(ctx context.Context, itemPath string) error { -// st.Lock() -// defer st.Unlock() -// return st.delFileInfo(ctx, itemPath) -// } - -// sharings - -func (st *SQLiteStore) SetSha1(ctx context.Context, userId uint64, itemPath, sign string) error { +func (st *SQLiteStore) SetSha1(ctx context.Context, itemPath, sign string) error { st.Lock() defer st.Unlock() - info, err := st.getFileInfo(ctx, userId, itemPath) + info, err := st.getFileInfo(ctx, itemPath) if err != nil { return err } @@ -199,10 +188,9 @@ func (st *SQLiteStore) SetSha1(ctx context.Context, userId uint64, itemPath, sig ctx, `update t_file_info set info=? - where path=? and user=?`, + where path=?`, infoStr, itemPath, - userId, ) return err } @@ -264,11 +252,17 @@ func (st *SQLiteStore) MoveFileInfos(ctx context.Context, userId uint64, oldPath st.Lock() defer st.Unlock() - info, err := st.getFileInfo(ctx, userId, oldPath) + info, err := st.getFileInfo(ctx, oldPath) if err != nil { + if errors.Is(err, db.ErrFileInfoNotFound) { + // info for file does not exist so no need to move it + // e.g. folder info is not created before + // TODO: but sometimes it could be a bug + return nil + } return err } - err = st.delFileInfo(ctx, userId, oldPath) + err = st.delFileInfo(ctx, oldPath) if err != nil { return err } diff --git a/src/db/rdb/sqlite/files_sharings.go b/src/db/rdb/sqlite/files_sharings.go index 5e8e691..3849b73 100644 --- a/src/db/rdb/sqlite/files_sharings.go +++ b/src/db/rdb/sqlite/files_sharings.go @@ -29,16 +29,29 @@ func (st *SQLiteStore) generateShareID(payload string) (string, error) { return fmt.Sprintf("%x", h.Sum(nil))[:7], nil } -func (st *SQLiteStore) IsSharing(ctx context.Context, userId uint64, dirPath string) bool { +func (st *SQLiteStore) IsSharing(ctx context.Context, userId uint64, dirPath string) (bool, error) { st.RLock() defer st.RUnlock() - // TODO: differentiate error and not exist - info, err := st.getFileInfo(ctx, userId, dirPath) + // TODO: userId is not used, becauser it is searcher's userId + var shareId string + err := st.db.QueryRowContext( + ctx, + `select share_id + from t_file_info + where path=?`, + dirPath, + ).Scan( + &shareId, + ) if err != nil { - return false + if errors.Is(err, sql.ErrNoRows) { + return false, db.ErrFileInfoNotFound + } + return false, err } - return info.ShareID != "" + + return shareId != "", nil } func (st *SQLiteStore) GetSharingDir(ctx context.Context, hashID string) (string, error) { @@ -75,7 +88,7 @@ func (st *SQLiteStore) AddSharing(ctx context.Context, userId uint64, dirPath st return err } - _, err = st.getFileInfo(ctx, userId, dirPath) + _, err = st.getFileInfo(ctx, dirPath) if err != nil && !errors.Is(err, db.ErrFileInfoNotFound) { return err } @@ -102,8 +115,8 @@ func (st *SQLiteStore) AddSharing(ctx context.Context, userId uint64, dirPath st ctx, `update t_file_info set share_id=? - where path=? and user=?`, - shareID, dirPath, userId, + where path=?`, + shareID, dirPath, ) return err } @@ -116,9 +129,8 @@ func (st *SQLiteStore) DelSharing(ctx context.Context, userId uint64, dirPath st ctx, `update t_file_info set share_id='' - where path=? and user=?`, + where path=?`, dirPath, - userId, ) return err } diff --git a/src/db/rdb/sqlite/files_uploadings.go b/src/db/rdb/sqlite/files_uploadings.go index 6bf3db7..b9aaa82 100644 --- a/src/db/rdb/sqlite/files_uploadings.go +++ b/src/db/rdb/sqlite/files_uploadings.go @@ -8,7 +8,7 @@ import ( "github.com/ihexxa/quickshare/src/db" ) -func (st *SQLiteStore) addUploadInfoOnly(ctx context.Context, userId uint64, filePath, tmpPath string, fileSize int64) error { +func (st *SQLiteStore) addUploadInfoOnly(ctx context.Context, userId uint64, tmpPath, filePath string, fileSize int64) error { _, err := st.db.ExecContext( ctx, `insert into t_file_uploading @@ -42,7 +42,7 @@ func (st *SQLiteStore) AddUploadInfos(ctx context.Context, userId uint64, tmpPat return err } - return st.addUploadInfoOnly(ctx, userId, filePath, tmpPath, info.Size) + return st.addUploadInfoOnly(ctx, userId, tmpPath, filePath, info.Size) } func (st *SQLiteStore) DelUploadingInfos(ctx context.Context, userId uint64, realPath string) error { @@ -82,22 +82,22 @@ func (st *SQLiteStore) delUploadInfoOnly(ctx context.Context, userId uint64, fil return err } -// func (st *SQLiteStore) MoveUploadingInfos(ctx context.Context, userId uint64, uploadPath, itemPath string) error { -// st.Lock() -// defer st.Unlock() +func (st *SQLiteStore) MoveUploadingInfos(ctx context.Context, userId uint64, uploadPath, itemPath string) error { + st.Lock() + defer st.Unlock() -// _, size, _, err := st.getUploadInfo(ctx, userId, itemPath) -// if err != nil { -// return err -// } -// err = st.delUploadInfoOnly(ctx, userId, itemPath) -// if err != nil { -// return err -// } -// return st.addFileInfo(ctx, userId, itemPath, &db.FileInfo{ -// Size: size, -// }) -// } + _, size, _, err := st.getUploadInfo(ctx, userId, itemPath) + if err != nil { + return err + } + err = st.delUploadInfoOnly(ctx, userId, itemPath) + if err != nil { + return err + } + return st.addFileInfo(ctx, userId, itemPath, &db.FileInfo{ + Size: size, + }) +} func (st *SQLiteStore) SetUploadInfo(ctx context.Context, userId uint64, filePath string, newUploaded int64) error { st.Lock() diff --git a/src/handlers/fileshdr/async_handlers.go b/src/handlers/fileshdr/async_handlers.go index 038a868..438a9a2 100644 --- a/src/handlers/fileshdr/async_handlers.go +++ b/src/handlers/fileshdr/async_handlers.go @@ -49,7 +49,7 @@ func (h *FileHandlers) genSha1(msg worker.IMsg) error { sha1Sign := fmt.Sprintf("%x", hasher.Sum(nil)) err = h.deps.FileInfos(). - SetSha1(context.TODO(), taskInputs.UserId, taskInputs.FilePath, sha1Sign) // TODO: use source context + SetSha1(context.TODO(), taskInputs.FilePath, sha1Sign) // TODO: use source context if err != nil { return fmt.Errorf("fail to set sha1: %s", err) } diff --git a/src/handlers/fileshdr/handlers.go b/src/handlers/fileshdr/handlers.go index a0e3cd5..84a6305 100644 --- a/src/handlers/fileshdr/handlers.go +++ b/src/handlers/fileshdr/handlers.go @@ -11,6 +11,7 @@ import ( "os" "path/filepath" "strings" + "sync" "time" "github.com/gin-gonic/gin" @@ -41,14 +42,16 @@ const ( ) type FileHandlers struct { - cfg gocfg.ICfg - deps *depidx.Deps + cfg gocfg.ICfg + deps *depidx.Deps + lockedPaths *sync.Map } func NewFileHandlers(cfg gocfg.ICfg, deps *depidx.Deps) (*FileHandlers, error) { handlers := &FileHandlers{ - cfg: cfg, - deps: deps, + cfg: cfg, + deps: deps, + lockedPaths: &sync.Map{}, } deps.Workers().AddHandler(MsgTypeSha1, handlers.genSha1) deps.Workers().AddHandler(MsgTypeIndexing, handlers.indexingItems) @@ -56,43 +59,26 @@ func NewFileHandlers(cfg gocfg.ICfg, deps *depidx.Deps) (*FileHandlers, error) { return handlers, nil } -type AutoLocker struct { - h *FileHandlers - c *gin.Context - key string -} - -func (h *FileHandlers) NewAutoLocker(c *gin.Context, key string) *AutoLocker { - return &AutoLocker{ - h: h, - c: c, - key: key, - } -} - -func (lk *AutoLocker) Exec(handler func()) error { - var err error - kv := lk.h.deps.KV() - locked := false +func (h *FileHandlers) lock(key string, code *int, err *error, execution func() (int, error)) { + var loaded bool defer func() { if p := recover(); p != nil { - lk.h.deps.Log().Error(p) + h.deps.Log().Error(p) + *code, *err = 500, fmt.Errorf("%s", p) } - if locked { - if err = kv.Unlock(lk.key); err != nil { - lk.h.deps.Log().Error(err) - } + if !loaded { + h.lockedPaths.Delete(key) } }() - if err = kv.TryLock(lk.key); err != nil { - return errors.New("fail to lock the file") + _, loaded = h.lockedPaths.LoadOrStore(key, true) + if loaded { + *code, *err = 429, fmt.Errorf("failed to lock: %s", key) + return } - locked = true - handler() - return nil + *code, *err = execution() } // related elements: role, user, action(listing, downloading)/sharing @@ -115,7 +101,10 @@ func (h *FileHandlers) canAccess(ctx context.Context, userId uint64, userName, r return false } - isSharing := h.deps.FileInfos().IsSharing(ctx, userId, sharedPath) + isSharing, err := h.deps.FileInfos().IsSharing(ctx, userId, sharedPath) + if err != nil { + return false // TODO: return error + } return isSharing } @@ -168,7 +157,7 @@ func (h *FileHandlers) Create(c *gin.Context) { } return } - err = h.deps.FileInfos().MoveFileInfos(c, userID, tmpFilePath, fsFilePath, false) + err = h.deps.FileInfos().MoveUploadingInfos(c, userID, tmpFilePath, fsFilePath) if err != nil { c.JSON(q.ErrResp(c, 500, err)) return @@ -233,35 +222,25 @@ func (h *FileHandlers) Create(c *gin.Context) { return } - var txErr error - locker := h.NewAutoLocker(c, lockName(tmpFilePath)) - lockErr := locker.Exec(func() { - err = h.deps.FS().Create(tmpFilePath) + var code int + h.lock(lockName(tmpFilePath), &code, &err, func() (int, error) { + err := h.deps.FS().Create(tmpFilePath) if err != nil { if os.IsExist(err) { createErr := fmt.Errorf("file(%s) exists", tmpFilePath) - c.JSON(q.ErrResp(c, 304, createErr)) - txErr = createErr - } else { - c.JSON(q.ErrResp(c, 500, err)) - txErr = err + return 304, createErr } - return + return 500, err } err = h.deps.FS().MkdirAll(filepath.Dir(req.Path)) if err != nil { - c.JSON(q.ErrResp(c, 500, err)) - txErr = err - return + return 500, err } + return 200, nil }) - if lockErr != nil { - c.JSON(q.ErrResp(c, 500, lockErr)) - return - } - if txErr != nil { - c.JSON(q.ErrResp(c, 500, txErr)) + if err != nil { + c.JSON(q.ErrResp(c, code, err)) return } c.JSON(q.Resp(200)) @@ -288,33 +267,28 @@ func (h *FileHandlers) Delete(c *gin.Context) { return } - var txErr error - locker := h.NewAutoLocker(c, lockName(filePath)) - lockErr := locker.Exec(func() { - err = h.deps.FS().Remove(filePath) + // var txErr error + // locker := h.NewAutoLocker(c, lockName(filePath)) + var code int + h.lock(lockName(filePath), &code, &err, func() (int, error) { + err := h.deps.FS().Remove(filePath) if err != nil { - txErr = err - return + return 500, err } err = h.deps.FileInfos().DelFileInfo(c, userId, filePath) if err != nil { - txErr = err - return + return 500, err } err = h.deps.FileIndex().DelPath(filePath) if err != nil && !errors.Is(err, fsearch.ErrNotFound) { - txErr = err - return + return 500, err } + return 200, nil }) - if lockErr != nil { - c.JSON(q.ErrResp(c, 500, lockErr)) - return - } - if txErr != nil { - c.JSON(q.ErrResp(c, 500, txErr)) + if err != nil { + c.JSON(q.ErrResp(c, code, err)) return } c.JSON(q.Resp(200)) @@ -510,53 +484,48 @@ func (h *FileHandlers) UploadChunk(c *gin.Context) { return } - var txErr error - var statusCode int + // var txErr error + // var statusCode int + // locker := h.NewAutoLocker(c, lockName(tmpFilePath)) tmpFilePath := q.UploadPath(userName, filePath) - locker := h.NewAutoLocker(c, lockName(tmpFilePath)) + var code int fsFilePath, fileSize, uploaded, wrote := "", int64(0), int64(0), 0 - lockErr := locker.Exec(func() { + h.lock(lockName(tmpFilePath), &code, &err, func() (int, error) { + // lockErr := locker.Exec(func() { var err error - fsFilePath, fileSize, uploaded, err = h.deps.FileInfos().GetUploadInfo(c, userId, tmpFilePath) + fsFilePath, fileSize, uploaded, err = h.deps.FileInfos().GetUploadInfo(c, userId, filePath) if err != nil { - txErr, statusCode = err, 500 - return + return 500, err } else if uploaded != req.Offset { - txErr, statusCode = errors.New("offset != uploaded"), 500 - return + return 500, errors.New("offset != uploaded") } content, err := base64.StdEncoding.DecodeString(req.Content) if err != nil { - txErr, statusCode = err, 500 - return + return 500, err } wrote, err = h.deps.FS().WriteAt(tmpFilePath, []byte(content), req.Offset) if err != nil { - txErr, statusCode = err, 500 - return + return 500, err } - err = h.deps.FileInfos().SetUploadInfo(c, userId, tmpFilePath, req.Offset+int64(wrote)) + err = h.deps.FileInfos().SetUploadInfo(c, userId, filePath, req.Offset+int64(wrote)) if err != nil { - txErr, statusCode = err, 500 - return + return 500, err } // move the file from uploading dir to uploaded dir if uploaded+int64(wrote) == fileSize { - err = h.deps.FileInfos().MoveFileInfos(c, userId, tmpFilePath, fsFilePath, false) + err = h.deps.FileInfos().MoveUploadingInfos(c, userId, tmpFilePath, fsFilePath) if err != nil { - txErr, statusCode = err, 500 - return + return 500, err } err = h.deps.FS().Rename(tmpFilePath, fsFilePath) if err != nil { - txErr, statusCode = fmt.Errorf("%s error: %w", fsFilePath, err), 500 - return + return 500, fmt.Errorf("%s error: %w", fsFilePath, err) } msg, err := json.Marshal(Sha1Params{ @@ -564,8 +533,7 @@ func (h *FileHandlers) UploadChunk(c *gin.Context) { FilePath: fsFilePath, }) if err != nil { - txErr, statusCode = err, 500 - return + return 500, err } err = h.deps.Workers().TryPut( @@ -576,24 +544,21 @@ func (h *FileHandlers) UploadChunk(c *gin.Context) { ), ) if err != nil { - txErr, statusCode = err, 500 - return + return 500, err } err = h.deps.FileIndex().AddPath(fsFilePath) if err != nil { - txErr, statusCode = err, 500 - return + return 500, err } } + return 200, nil }) - if lockErr != nil { - c.JSON(q.ErrResp(c, 500, err)) - } - if txErr != nil { - c.JSON(q.ErrResp(c, statusCode, txErr)) + if err != nil { + c.JSON(q.ErrResp(c, code, err)) return } + c.JSON(200, &UploadStatusResp{ Path: fsFilePath, IsDir: false, @@ -667,32 +632,28 @@ func (h *FileHandlers) UploadStatus(c *gin.Context) { return } + // locker := h.NewAutoLocker(c, lockName(tmpFilePath)) + // var txErr error tmpFilePath := q.UploadPath(userName, filePath) - locker := h.NewAutoLocker(c, lockName(tmpFilePath)) fileSize, uploaded := int64(0), int64(0) - var txErr error - lockErr := locker.Exec(func() { + var code int + h.lock(lockName(tmpFilePath), &code, &err, func() (int, error) { + // lockErr := locker.Exec(func() { var err error - _, fileSize, uploaded, err = h.deps.FileInfos().GetUploadInfo(c, userId, tmpFilePath) + _, fileSize, uploaded, err = h.deps.FileInfos().GetUploadInfo(c, userId, filePath) if err != nil { if os.IsNotExist(err) { - c.JSON(q.ErrResp(c, 404, err)) - txErr = err - } else { - c.JSON(q.ErrResp(c, 500, err)) - txErr = err + return 404, err } - return + return 500, err } + return 200, nil }) - if lockErr != nil { - c.JSON(q.ErrResp(c, 500, lockErr)) - return - } - if txErr != nil { - c.JSON(q.ErrResp(c, 500, txErr)) + if err != nil { + c.JSON(q.ErrResp(c, code, err)) return } + c.JSON(200, &UploadStatusResp{ Path: filePath, IsDir: false, @@ -981,35 +942,32 @@ func (h *FileHandlers) DelUploading(c *gin.Context) { return } - var txErr error - var statusCode int + // var txErr error + // var statusCode int tmpFilePath := q.UploadPath(userName, filePath) - locker := h.NewAutoLocker(c, lockName(tmpFilePath)) - lockErr := locker.Exec(func() { + // locker := h.NewAutoLocker(c, lockName(tmpFilePath)) + // lockErr := locker.Exec(func() { + var code int + h.lock(lockName(tmpFilePath), &code, &err, func() (int, error) { _, err = h.deps.FS().Stat(tmpFilePath) if err != nil { if os.IsNotExist(err) { // no op } else { - txErr, statusCode = err, 500 - return - } - } else { - err = h.deps.FS().Remove(tmpFilePath) - if err != nil { - txErr, statusCode = err, 500 - return + return 500, err } } + err = h.deps.FS().Remove(tmpFilePath) + if err != nil { + return 500, err + } + return 200, nil }) - if lockErr != nil { - c.JSON(q.ErrResp(c, 500, lockErr)) - return - } - if txErr != nil { - c.JSON(q.ErrResp(c, statusCode, txErr)) + if err != nil { + c.JSON(q.ErrResp(c, code, err)) return } + err = h.deps.FileInfos().DelUploadingInfos(c, userId, filePath) if err != nil { c.JSON(q.ErrResp(c, 500, err)) @@ -1111,8 +1069,14 @@ func (h *FileHandlers) IsSharing(c *gin.Context) { return } - exist := h.deps.FileInfos().IsSharing(c, userId, dirPath) - if exist { + exist, err := h.deps.FileInfos().IsSharing(c, userId, dirPath) + if err != nil { + if errors.Is(err, db.ErrFileInfoNotFound) { + c.JSON(q.Resp(404)) + } else { + c.JSON(q.Resp(500)) + } + } else if exist { c.JSON(q.Resp(200)) } else { c.JSON(q.Resp(404)) diff --git a/src/handlers/multiusers/handlers.go b/src/handlers/multiusers/handlers.go index e026783..2164f64 100644 --- a/src/handlers/multiusers/handlers.go +++ b/src/handlers/multiusers/handlers.go @@ -145,7 +145,7 @@ func NewMultiUsersSvc(cfg gocfg.ICfg, deps *depidx.Deps) (*MultiUsersSvc, error) return handlers, nil } -func (h *MultiUsersSvc) Init(ctx context.Context, adminName, adminPwd string) (string, error) { +func (h *MultiUsersSvc) Init(ctx context.Context, adminName string) (string, error) { var err error fsPath := q.FsRootPath(adminName, "/") diff --git a/src/handlers/util.go b/src/handlers/util.go index 8d16557..ecf9d86 100644 --- a/src/handlers/util.go +++ b/src/handlers/util.go @@ -8,8 +8,8 @@ import ( "strconv" "github.com/gin-gonic/gin" - "github.com/ihexxa/quickshare/src/cryptoutil" + "github.com/ihexxa/quickshare/src/db" ) var ( @@ -171,6 +171,8 @@ func GetUserId(ctx *gin.Context) (uint64, error) { if !ok { return 0, errors.New("user id not found") } - + if userID == "" { + return db.VisitorID, nil + } return strconv.ParseUint(userID, 10, 64) } diff --git a/src/server/config.go b/src/server/config.go index 6db8e2d..d336716 100644 --- a/src/server/config.go +++ b/src/server/config.go @@ -9,8 +9,7 @@ import ( const fileIndexPath = "/fileindex.jsonl" type DbConfig struct { - DbPath string `json:"dbPath" yaml:"dbPath"` - RdbPath string `json:"rdbPath" yaml:"rdbPath"` // valid values: rdb, kv + DbPath string `json:"dbPath" yaml:"dbPath"` } type FSConfig struct { @@ -141,8 +140,7 @@ func DefaultConfigStruct() *Config { }, }, Db: &DbConfig{ - DbPath: "quickshare.db", - RdbPath: "quickshare.sqlite", + DbPath: "quickshare.sqlite", }, } } diff --git a/src/server/server.go b/src/server/server.go index fb75fa9..27abe04 100644 --- a/src/server/server.go +++ b/src/server/server.go @@ -57,9 +57,9 @@ func NewServer(cfg gocfg.ICfg) (*Server, error) { gin.SetMode(gin.ReleaseMode) } - deps := initDeps(cfg) + deps, adminName := initDeps(cfg) router := gin.Default() - router, err := initHandlers(router, cfg, deps) + router, err := initHandlers(router, adminName, cfg, deps) if err != nil { return nil, fmt.Errorf("init handlers error: %w", err) } @@ -104,7 +104,7 @@ func mkRoot(rootPath string) { } } -func initDeps(cfg gocfg.ICfg) *depidx.Deps { +func initDeps(cfg gocfg.ICfg) (*depidx.Deps, string) { var err error logger := initLogger(cfg) @@ -142,7 +142,7 @@ func initDeps(cfg gocfg.ICfg) *depidx.Deps { // panic(fmt.Sprintf("failed to init bolt store: %s", err)) // } - quickshareDb, err := initDB(cfg, filesystem) + quickshareDb, adminName, err := initDB(cfg, filesystem) if err != nil { logger.Errorf("failed to init DB: %s", err) os.Exit(1) @@ -197,25 +197,25 @@ func initDeps(cfg gocfg.ICfg) *depidx.Deps { logger.Infof("file index inited(%t)", indexInited) deps.SetFileIndex(fileIndex) - return deps + return deps, adminName } -func initDB(cfg gocfg.ICfg, filesystem fs.ISimpleFS) (db.IDBQuickshare, error) { +func initDB(cfg gocfg.ICfg, filesystem fs.ISimpleFS) (db.IDBQuickshare, string, error) { dbPath := cfg.GrabString("Db.DbPath") dbDir := path.Dir(dbPath) err := filesystem.MkdirAll(dbDir) if err != nil { - return nil, fmt.Errorf("failed to create path for db: %w", err) + return nil, "", fmt.Errorf("failed to create path for db: %w", err) } sqliteDB, err := sqlite.NewSQLite(dbPath) if err != nil { - return nil, fmt.Errorf("failed to create path for db: %w", err) + return nil, "", fmt.Errorf("failed to create path for db: %w", err) } dbQuickshare, err := sqlite.NewSQLiteStore(sqliteDB) if err != nil { - return nil, fmt.Errorf("failed to create quickshare db: %w", err) + return nil, "", fmt.Errorf("failed to create quickshare db: %w", err) } var ok bool @@ -232,20 +232,20 @@ func initDB(cfg gocfg.ICfg, filesystem fs.ISimpleFS) (db.IDBQuickshare, error) { if adminPwd == "" { adminPwd, err = generatePwd() if err != nil { - return nil, fmt.Errorf("generate password error: %w", err) + return nil, "", fmt.Errorf("generate password error: %w", err) } fmt.Printf("password is generated: %s, please update it immediately after login\n", adminPwd) } pwdHash, err = bcrypt.GenerateFromPassword([]byte(adminPwd), 10) if err != nil { - return nil, fmt.Errorf("hashing password error: %w", err) + return nil, "", fmt.Errorf("hashing password error: %w", err) } } err = dbQuickshare.InitUserTable(context.TODO(), adminName, string(pwdHash)) if err != nil { - return nil, fmt.Errorf("failed to init user table: %w", err) + return nil, "", fmt.Errorf("failed to init user table: %w", err) } err = dbQuickshare.InitConfigTable( context.TODO(), @@ -264,21 +264,26 @@ func initDB(cfg gocfg.ICfg, filesystem fs.ISimpleFS) (db.IDBQuickshare, error) { }, ) if err != nil { - return nil, fmt.Errorf("failed to init config table: %w", err) + return nil, "", fmt.Errorf("failed to init config table: %w", err) } err = dbQuickshare.InitFileTables(context.TODO()) if err != nil { - return nil, fmt.Errorf("failed to init files tables: %w", err) + return nil, "", fmt.Errorf("failed to init files tables: %w", err) } - return dbQuickshare, nil + return dbQuickshare, adminName, nil } -func initHandlers(router *gin.Engine, cfg gocfg.ICfg, deps *depidx.Deps) (*gin.Engine, error) { +func initHandlers(router *gin.Engine, adminName string, cfg gocfg.ICfg, deps *depidx.Deps) (*gin.Engine, error) { // handlers userHdrs, err := multiusers.NewMultiUsersSvc(cfg, deps) if err != nil { return nil, fmt.Errorf("new users svc error: %w", err) } + _, err = userHdrs.Init(context.TODO(), adminName) + if err != nil { + return nil, fmt.Errorf("failed to init user handlers: %w", err) + } + fileHdrs, err := fileshdr.NewFileHandlers(cfg, deps) if err != nil { return nil, fmt.Errorf("new files service error: %w", err) @@ -323,10 +328,10 @@ func initHandlers(router *gin.Engine, cfg gocfg.ICfg, deps *depidx.Deps) (*gin.E usersAPI.PATCH("/preferences", userHdrs.SetPreferences) usersAPI.PUT("/used-space", userHdrs.ResetUsedSpace) - rolesAPI := v1.Group("/roles") - rolesAPI.POST("/", userHdrs.AddRole) - rolesAPI.DELETE("/", userHdrs.DelRole) - rolesAPI.GET("/list", userHdrs.ListRoles) + // rolesAPI := v1.Group("/roles") + // rolesAPI.POST("/", userHdrs.AddRole) + // rolesAPI.DELETE("/", userHdrs.DelRole) + // rolesAPI.GET("/list", userHdrs.ListRoles) captchaAPI := v1.Group("/captchas") captchaAPI.GET("/", userHdrs.GetCaptchaID) diff --git a/src/server/server_files_test.go b/src/server/server_files_test.go index 48643a2..f577254 100644 --- a/src/server/server_files_test.go +++ b/src/server/server_files_test.go @@ -452,6 +452,8 @@ func TestFileHandlers(t *testing.T) { t.Fatal(errs) } else if res.StatusCode != 200 { t.Fatal(res.StatusCode) + } else if len(shRes.IDs) != len(sharedPaths) { + t.Fatal("shared size not match") } for dirPath, shareID := range shRes.IDs { if !sharedPaths[dirPath] { @@ -469,6 +471,7 @@ func TestFileHandlers(t *testing.T) { } } + fmt.Println("\n\n\n", shRes.IDs) // check isSharing for dirPath := range sharedPaths { res, _, errs := userFilesCl.IsSharing(dirPath) @@ -673,7 +676,7 @@ func TestFileHandlers(t *testing.T) { } else if res.StatusCode != 200 { t.Fatal(res.StatusCode) } else if len(lResp.UploadInfos) != 0 { - t.Fatalf("info is not deleted, info len(%d)", len(lResp.UploadInfos)) + t.Fatalf("info is not deleted, info len(%+v)", lResp.UploadInfos) } }) @@ -828,7 +831,7 @@ func TestFileHandlers(t *testing.T) { res, _, errs = adminFilesClient.IsSharing(dstDir) if len(errs) > 0 { t.Fatal(errs) - } else if res.StatusCode != 404 { // should not be in sharing + } else if res.StatusCode != 200 { // should still be in sharing t.Fatal(res.StatusCode) } diff --git a/src/server/server_permission_test.go b/src/server/server_permission_test.go index 9ecf59e..8e3af5d 100644 --- a/src/server/server_permission_test.go +++ b/src/server/server_permission_test.go @@ -112,7 +112,7 @@ func TestPermissions(t *testing.T) { } tmpUser, tmpPwd, tmpRole := "tmpUser", "1234", "user" tmpAdmin, tmpAdminPwd := "tmpAdmin", "1234" - tmpNewRole := "tmpNewRole" + // tmpNewRole := "tmpNewRole" cl := client.NewUsersClient(addr) // token := &http.Cookie{} @@ -204,14 +204,14 @@ func TestPermissions(t *testing.T) { assertResp(t, resp, errs, expectedCodes["DelUserAdmin"], fmt.Sprintf("%s-%s", desc, "DelUserAdmin")) // role management - resp, _, errs = cl.AddRole(tmpNewRole) - assertResp(t, resp, errs, expectedCodes["AddRole"], fmt.Sprintf("%s-%s", desc, "AddRole")) + // resp, _, errs = cl.AddRole(tmpNewRole) + // assertResp(t, resp, errs, expectedCodes["AddRole"], fmt.Sprintf("%s-%s", desc, "AddRole")) - resp, _, errs = cl.ListRoles() - assertResp(t, resp, errs, expectedCodes["ListRoles"], fmt.Sprintf("%s-%s", desc, "ListRoles")) + // resp, _, errs = cl.ListRoles() + // assertResp(t, resp, errs, expectedCodes["ListRoles"], fmt.Sprintf("%s-%s", desc, "ListRoles")) - resp, _, errs = cl.DelRole(tmpNewRole) - assertResp(t, resp, errs, expectedCodes["DelRole"], fmt.Sprintf("%s-%s", desc, "DelRole")) + // resp, _, errs = cl.DelRole(tmpNewRole) + // assertResp(t, resp, errs, expectedCodes["DelRole"], fmt.Sprintf("%s-%s", desc, "DelRole")) if requireAuth { resp, _, errs := cl.Logout() diff --git a/src/server/server_users_test.go b/src/server/server_users_test.go index 5d4795f..c40746a 100644 --- a/src/server/server_users_test.go +++ b/src/server/server_users_test.go @@ -384,71 +384,71 @@ func TestUsersHandlers(t *testing.T) { } }) - t.Run("test roles APIs: Login-AddRole-ListRoles-DelRole-ListRoles-Logout", func(t *testing.T) { - adminUsersCli := client.NewUsersClient(addr) - resp, _, errs := adminUsersCli.Login(adminName, adminNewPwd) - if len(errs) > 0 { - t.Fatal(errs) - } else if resp.StatusCode != 200 { - t.Fatal(resp.StatusCode) - } + // t.Run("test roles APIs: Login-AddRole-ListRoles-DelRole-ListRoles-Logout", func(t *testing.T) { + // adminUsersCli := client.NewUsersClient(addr) + // resp, _, errs := adminUsersCli.Login(adminName, adminNewPwd) + // if len(errs) > 0 { + // t.Fatal(errs) + // } else if resp.StatusCode != 200 { + // t.Fatal(resp.StatusCode) + // } - // token := client.GetCookie(resp.Cookies(), su.TokenCookie) - roles := []string{"role1", "role2"} + // // token := client.GetCookie(resp.Cookies(), su.TokenCookie) + // roles := []string{"role1", "role2"} - for _, role := range roles { - resp, _, errs := adminUsersCli.AddRole(role) - if len(errs) > 0 { - t.Fatal(errs) - } else if resp.StatusCode != 200 { - t.Fatal(resp.StatusCode) - } - } + // for _, role := range roles { + // resp, _, errs := adminUsersCli.AddRole(role) + // if len(errs) > 0 { + // t.Fatal(errs) + // } else if resp.StatusCode != 200 { + // t.Fatal(resp.StatusCode) + // } + // } - resp, lsResp, errs := adminUsersCli.ListRoles() - if len(errs) > 0 { - t.Fatal(errs) - } else if resp.StatusCode != 200 { - t.Fatal(resp.StatusCode) - } - for _, role := range append(roles, []string{ - db.AdminRole, - db.UserRole, - db.VisitorRole, - }...) { - if !lsResp.Roles[role] { - t.Fatalf("role(%s) not found", role) - } - } + // resp, lsResp, errs := adminUsersCli.ListRoles() + // if len(errs) > 0 { + // t.Fatal(errs) + // } else if resp.StatusCode != 200 { + // t.Fatal(resp.StatusCode) + // } + // for _, role := range append(roles, []string{ + // db.AdminRole, + // db.UserRole, + // db.VisitorRole, + // }...) { + // if !lsResp.Roles[role] { + // t.Fatalf("role(%s) not found", role) + // } + // } - for _, role := range roles { - resp, _, errs := adminUsersCli.DelRole(role) - if len(errs) > 0 { - t.Fatal(errs) - } else if resp.StatusCode != 200 { - t.Fatal(resp.StatusCode) - } - } + // for _, role := range roles { + // resp, _, errs := adminUsersCli.DelRole(role) + // if len(errs) > 0 { + // t.Fatal(errs) + // } else if resp.StatusCode != 200 { + // t.Fatal(resp.StatusCode) + // } + // } - resp, lsResp, errs = adminUsersCli.ListRoles() - if len(errs) > 0 { - t.Fatal(errs) - } else if resp.StatusCode != 200 { - t.Fatal(resp.StatusCode) - } - for _, role := range roles { - if lsResp.Roles[role] { - t.Fatalf("role(%s) should not exist", role) - } - } + // resp, lsResp, errs = adminUsersCli.ListRoles() + // if len(errs) > 0 { + // t.Fatal(errs) + // } else if resp.StatusCode != 200 { + // t.Fatal(resp.StatusCode) + // } + // for _, role := range roles { + // if lsResp.Roles[role] { + // t.Fatalf("role(%s) should not exist", role) + // } + // } - resp, _, errs = adminUsersCli.Logout() - if len(errs) > 0 { - t.Fatal(errs) - } else if resp.StatusCode != 200 { - t.Fatal(resp.StatusCode) - } - }) + // resp, _, errs = adminUsersCli.Logout() + // if len(errs) > 0 { + // t.Fatal(errs) + // } else if resp.StatusCode != 200 { + // t.Fatal(resp.StatusCode) + // } + // }) t.Run("Login, SetPreferences, Self, Logout", func(t *testing.T) { adminUsersCli := client.NewUsersClient(addr)