test(server): fix bugs and tests

This commit is contained in:
hexxa 2022-09-03 23:32:32 +08:00 committed by Hexxa
parent 4265ab593e
commit ce77eb7534
13 changed files with 266 additions and 288 deletions

View file

@ -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

View file

@ -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
}

View file

@ -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
}

View file

@ -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()

View file

@ -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)
}

View file

@ -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))

View file

@ -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, "/")

View file

@ -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)
}

View file

@ -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",
},
}
}

View file

@ -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)

View file

@ -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)
}

View file

@ -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()

View file

@ -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)