From 4dcd2c56ca166dbed2a61b302c791c1311b0a60d Mon Sep 17 00:00:00 2001 From: hexxa Date: Wed, 9 Mar 2022 15:29:38 +0800 Subject: [PATCH] feat(users) add async handler for reset used space --- src/db/userstore/user_store.go | 27 ++++++++++++ src/handlers/fileshdr/async_handlers.go | 4 +- src/handlers/multiusers/async_handlers.go | 48 ++++++++++++++++++++ src/handlers/multiusers/handlers.go | 51 +++++++++++++++++++++- src/server/server.go | 1 + src/server/testdata/test_quickshare.db | Bin 524288 -> 524288 bytes src/worker/interface.go | 5 ++- src/worker/localworker/worker.go | 10 +++++ 8 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 src/handlers/multiusers/async_handlers.go diff --git a/src/db/userstore/user_store.go b/src/db/userstore/user_store.go index d2292bc..e33619c 100644 --- a/src/db/userstore/user_store.go +++ b/src/db/userstore/user_store.go @@ -67,6 +67,7 @@ type IUserStore interface { SetInfo(id uint64, user *db.User) error CanIncrUsed(id uint64, capacity int64) (bool, error) SetUsed(id uint64, incr bool, capacity int64) error + ResetUsed(id uint64, used int64) error SetPwd(id uint64, pwd string) error SetPreferences(id uint64, settings *db.Preferences) error ListUsers() ([]*db.User, error) @@ -369,6 +370,32 @@ func (us *KVUserStore) SetUsed(id uint64, incr bool, capacity int64) error { return us.store.SetStringIn(db.UsersNs, userID, string(infoBytes)) } +func (us *KVUserStore) ResetUsed(id uint64, used int64) error { + us.mtx.Lock() + defer us.mtx.Unlock() + + userID := fmt.Sprint(id) + infoStr, ok := us.store.GetStringIn(db.UsersNs, userID) + if !ok { + return fmt.Errorf("user (%d) does not exist", id) + } + + gotUser := &db.User{} + err := json.Unmarshal([]byte(infoStr), gotUser) + if err != nil { + return err + } else if gotUser.ID != id { + return fmt.Errorf("user id key(%d) info(%d) does match", id, gotUser.ID) + } + + gotUser.UsedSpace = used + infoBytes, err := json.Marshal(gotUser) + if err != nil { + return err + } + return us.store.SetStringIn(db.UsersNs, userID, string(infoBytes)) +} + func (us *KVUserStore) SetInfo(id uint64, user *db.User) error { us.mtx.Lock() defer us.mtx.Unlock() diff --git a/src/handlers/fileshdr/async_handlers.go b/src/handlers/fileshdr/async_handlers.go index a000640..6a6ae59 100644 --- a/src/handlers/fileshdr/async_handlers.go +++ b/src/handlers/fileshdr/async_handlers.go @@ -9,7 +9,9 @@ import ( "github.com/ihexxa/quickshare/src/worker" ) -const MsgTypeSha1 = "sha1" +const ( + MsgTypeSha1 = "sha1" +) type Sha1Params struct { FilePath string diff --git a/src/handlers/multiusers/async_handlers.go b/src/handlers/multiusers/async_handlers.go new file mode 100644 index 0000000..9829b3b --- /dev/null +++ b/src/handlers/multiusers/async_handlers.go @@ -0,0 +1,48 @@ +package multiusers + +import ( + "encoding/json" + "fmt" + "path/filepath" + + "github.com/ihexxa/quickshare/src/worker" +) + +const ( + MsgTypeResetUsedSpace = "reset-used-space" +) + +type UsedSpaceParams struct { + UserID uint64 + UserHomePath string +} + +func (h *MultiUsersSvc) resetUsedSpace(msg worker.IMsg) error { + params := &UsedSpaceParams{} + err := json.Unmarshal([]byte(msg.Body()), params) + if err != nil { + return fmt.Errorf("fail to unmarshal sha1 msg: %w", err) + } + + usedSpace := int64(0) + dirQueue := []string{params.UserHomePath} + for len(dirQueue) > 0 { + dirPath := dirQueue[0] + dirQueue = dirQueue[1:] + + infos, err := h.deps.FS().ListDir(dirPath) + if err != nil { + return err + } + + for _, info := range infos { + if info.IsDir() { + dirQueue = append(dirQueue, filepath.Join(dirPath, info.Name())) + } else { + usedSpace += info.Size() + } + } + } + + return h.deps.Users().ResetUsed(params.UserID, usedSpace) +} diff --git a/src/handlers/multiusers/handlers.go b/src/handlers/multiusers/handlers.go index d699d48..61e4a47 100644 --- a/src/handlers/multiusers/handlers.go +++ b/src/handlers/multiusers/handlers.go @@ -1,6 +1,7 @@ package multiusers import ( + "encoding/json" "errors" "fmt" "path/filepath" @@ -16,6 +17,7 @@ import ( "github.com/ihexxa/quickshare/src/db/userstore" "github.com/ihexxa/quickshare/src/depidx" q "github.com/ihexxa/quickshare/src/handlers" + "github.com/ihexxa/quickshare/src/worker/localworker" ) var ( @@ -48,6 +50,7 @@ func NewMultiUsersSvc(cfg gocfg.ICfg, deps *depidx.Deps) (*MultiUsersSvc, error) apiRuleCname(userstore.AdminRole, "GET", "/v1/users/list"): true, apiRuleCname(userstore.AdminRole, "GET", "/v1/users/self"): true, apiRuleCname(userstore.AdminRole, "PATCH", "/v1/users/preferences"): true, + apiRuleCname(userstore.AdminRole, "PUT", "/v1/users//used-space"): true, apiRuleCname(userstore.AdminRole, "POST", "/v1/roles/"): true, apiRuleCname(userstore.AdminRole, "DELETE", "/v1/roles/"): true, apiRuleCname(userstore.AdminRole, "GET", "/v1/roles/list"): true, @@ -77,6 +80,7 @@ func NewMultiUsersSvc(cfg gocfg.ICfg, deps *depidx.Deps) (*MultiUsersSvc, error) apiRuleCname(userstore.AdminRole, "GET", "/v1/fs/sharings/dirs"): true, apiRuleCname(userstore.AdminRole, "GET", "/v1/fs/sharings/ids"): true, apiRuleCname(userstore.AdminRole, "POST", "/v1/fs/hashes/sha1"): true, + // user rules apiRuleCname(userstore.UserRole, "GET", "/"): true, apiRuleCname(userstore.UserRole, "GET", publicPath): true, @@ -125,11 +129,14 @@ func NewMultiUsersSvc(cfg gocfg.ICfg, deps *depidx.Deps) (*MultiUsersSvc, error) apiRuleCname(userstore.VisitorRole, "GET", "/v1/fs/sharings/dirs"): true, } - return &MultiUsersSvc{ + handlers := &MultiUsersSvc{ cfg: cfg, deps: deps, apiACRules: apiACRules, - }, nil + } + deps.Workers().AddHandler(MsgTypeResetUsedSpace, handlers.resetUsedSpace) + + return handlers, nil } func (h *MultiUsersSvc) Init(adminName, adminPwd string) (string, error) { @@ -707,3 +714,43 @@ func (h *MultiUsersSvc) SetPreferences(c *gin.Context) { } c.JSON(q.Resp(200)) } + +type ResetUsedSpaceReq struct { + UserID uint64 `json:"userID,string"` +} + +func (h *MultiUsersSvc) ResetUsedSpace(c *gin.Context) { + req := &ResetUsedSpaceReq{} + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(q.ErrResp(c, 400, err)) + return + } + + userInfo, err := h.deps.Users().GetUser(req.UserID) + if err != nil { + c.JSON(q.ErrResp(c, 500, err)) + return + } + msg, err := json.Marshal(UsedSpaceParams{ + UserID: req.UserID, + UserHomePath: userInfo.Name, + }) + if err != nil { + c.JSON(q.ErrResp(c, 500, err)) + return + } + + err = h.deps.Workers().TryPut( + localworker.NewMsg( + h.deps.ID().Gen(), + map[string]string{localworker.MsgTypeKey: MsgTypeResetUsedSpace}, + string(msg), + ), + ) + if err != nil { + c.JSON(q.ErrResp(c, 500, err)) + return + } + + c.JSON(q.Resp(200)) +} diff --git a/src/server/server.go b/src/server/server.go index 0e52849..98a59b7 100644 --- a/src/server/server.go +++ b/src/server/server.go @@ -275,6 +275,7 @@ func initHandlers(router *gin.Engine, cfg gocfg.ICfg, deps *depidx.Deps) (*gin.E usersAPI.GET("/self", userHdrs.Self) usersAPI.PATCH("/", userHdrs.SetUser) usersAPI.PATCH("/preferences", userHdrs.SetPreferences) + usersAPI.PUT("/used-space", userHdrs.ResetUsedSpace) rolesAPI := v1.Group("/roles") rolesAPI.POST("/", userHdrs.AddRole) diff --git a/src/server/testdata/test_quickshare.db b/src/server/testdata/test_quickshare.db index 32e60828e9261c1eb305aec9a5a93463b53b8f4d..1d9535b1e77c7f0d45ad269c729d48b00042341a 100644 GIT binary patch delta 81 zcmZo@P-tjSnBX9=j)9Q@1f1(8O#Z&pcJ_9|0LBgclLQlgn3 delta 81 zcmZo@P-tjSnBX9AjDe8>1f*Z;-0NMycVxR^0OJP!NdgW6$DuNZi=W1<^e|ruk!ezB aQ($aUU}{rfZc|`sQ($dVU|XiZ{r~{ 0 { wp.logger.Infof(