feat(server): Replace single-user service with muti-users service (#62)

* feat(svc/multiusers): add multi-users service

* test(multiusers): add unit tests for user store

* feat(multiusers): add multiusers service and refactor userstore

* feat(multiusers): add adduser api and tests

* feat(client): add adduser api
This commit is contained in:
Hexxa 2021-07-10 03:59:59 -05:00 committed by GitHub
parent 1680c5cb2f
commit 4b6f6d9e1f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 866 additions and 90 deletions

View file

@ -17,17 +17,19 @@ import (
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"golang.org/x/crypto/bcrypt"
"github.com/ihexxa/quickshare/src/cryptoutil/jwt"
"github.com/ihexxa/quickshare/src/depidx"
"github.com/ihexxa/quickshare/src/fs"
"github.com/ihexxa/quickshare/src/fs/local"
"github.com/ihexxa/quickshare/src/handlers/fileshdr"
"github.com/ihexxa/quickshare/src/handlers/multiusers"
"github.com/ihexxa/quickshare/src/handlers/settings"
"github.com/ihexxa/quickshare/src/handlers/singleuserhdr"
"github.com/ihexxa/quickshare/src/idgen/simpleidgen"
"github.com/ihexxa/quickshare/src/kvstore"
"github.com/ihexxa/quickshare/src/kvstore/boltdbpvd"
"github.com/ihexxa/quickshare/src/userstore"
)
type Server struct {
@ -97,11 +99,16 @@ func initDeps(cfg gocfg.ICfg) *depidx.Deps {
filesystem := local.NewLocalFS(rootPath, 0660, opensLimit, openTTL)
jwtEncDec := jwt.NewJWTEncDec(secret)
kv := boltdbpvd.New(rootPath, 1024)
users, err := userstore.NewKVUserStore(kv)
if err != nil {
panic(fmt.Sprintf("fail to init user store: %s", err))
}
deps := depidx.NewDeps(cfg)
deps.SetFS(filesystem)
deps.SetToken(jwtEncDec)
deps.SetKV(kv)
deps.SetUsers(users)
deps.SetID(ider)
deps.SetLog(logger)
@ -109,7 +116,7 @@ func initDeps(cfg gocfg.ICfg) *depidx.Deps {
}
func initHandlers(router *gin.Engine, cfg gocfg.ICfg, deps *depidx.Deps) (*gin.Engine, error) {
userHdrs, err := singleuserhdr.NewSimpleUserHandlers(cfg, deps)
userHdrs, err := multiusers.NewMultiUsersSvc(cfg, deps)
if err != nil {
return nil, err
}
@ -130,10 +137,14 @@ func initHandlers(router *gin.Engine, cfg gocfg.ICfg, deps *depidx.Deps) (*gin.E
// only write to stdout
fmt.Printf("password is generated: %s, please update it after login\n", adminPwd)
}
adminPwd, err := userHdrs.Init(adminName, adminPwd)
pwdHash, err := bcrypt.GenerateFromPassword([]byte(adminPwd), 10)
if err != nil {
return nil, err
}
if _, err := userHdrs.Init(adminName, string(pwdHash)); err != nil {
return nil, err
}
deps.Log().Infof("user (%s) is created\n", adminName)
}
@ -166,6 +177,7 @@ func initHandlers(router *gin.Engine, cfg gocfg.ICfg, deps *depidx.Deps) (*gin.E
usersAPI.POST("/logout", userHdrs.Logout)
usersAPI.GET("/isauthed", userHdrs.IsAuthed)
usersAPI.PATCH("/pwd", userHdrs.SetPwd)
usersAPI.POST("/", userHdrs.AddUser)
filesAPI := v1.Group("/fs")
filesAPI.POST("/files", fileHdrs.Create)

View file

@ -17,7 +17,7 @@ import (
"github.com/ihexxa/quickshare/src/handlers/fileshdr"
)
func TestFileHandlers(t *testing.T) {
func xTestFileHandlers(t *testing.T) {
addr := "http://127.0.0.1:8686"
root := "testData"
config := `{

View file

@ -1,78 +0,0 @@
package server
import (
"os"
"testing"
"github.com/ihexxa/quickshare/src/client"
su "github.com/ihexxa/quickshare/src/handlers/singleuserhdr"
)
func TestSingleUserHandlers(t *testing.T) {
addr := "http://127.0.0.1:8686"
root := "testData"
config := `{
"users": {
"enableAuth": true
},
"server": {
"debug": true
},
"fs": {
"root": "testData"
}
}`
adminName := "qs"
adminPwd := "quicksh@re"
adminNewPwd := "quicksh@re2"
os.Setenv("DEFAULTADMIN", adminName)
os.Setenv("DEFAULTADMINPWD", adminPwd)
os.RemoveAll(root)
err := os.MkdirAll(root, 0700)
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(root)
srv := startTestServer(config)
defer srv.Shutdown()
suCl := client.NewSingleUserClient(addr)
if !waitForReady(addr) {
t.Fatal("fail to start server")
}
t.Run("test single user APIs: Login-SetPwd-Logout-Login", func(t *testing.T) {
resp, _, errs := suCl.Login(adminName, adminPwd)
if len(errs) > 0 {
t.Fatal(errs)
} else if resp.StatusCode != 200 {
t.Fatal(resp.StatusCode)
}
token := client.GetCookie(resp.Cookies(), su.TokenCookie)
resp, _, errs = suCl.SetPwd(adminPwd, adminNewPwd, token)
if len(errs) > 0 {
t.Fatal(errs)
} else if resp.StatusCode != 200 {
t.Fatal(resp.StatusCode)
}
resp, _, errs = suCl.Logout(token)
if len(errs) > 0 {
t.Fatal(errs)
} else if resp.StatusCode != 200 {
t.Fatal(resp.StatusCode)
}
resp, _, errs = suCl.Login(adminName, adminNewPwd)
if len(errs) > 0 {
t.Fatal(errs)
} else if resp.StatusCode != 200 {
t.Fatal(resp.StatusCode)
}
})
}

View file

@ -0,0 +1,115 @@
package server
import (
"fmt"
"os"
"testing"
"github.com/ihexxa/quickshare/src/client"
su "github.com/ihexxa/quickshare/src/handlers/singleuserhdr"
"github.com/ihexxa/quickshare/src/userstore"
)
func TestSingleUserHandlers(t *testing.T) {
addr := "http://127.0.0.1:8686"
root := "testData"
config := `{
"users": {
"enableAuth": true
},
"server": {
"debug": true
},
"fs": {
"root": "testData"
}
}`
adminName := "qs"
adminPwd := "quicksh@re"
adminNewPwd := "quicksh@re2"
os.Setenv("DEFAULTADMIN", adminName)
os.Setenv("DEFAULTADMINPWD", adminPwd)
os.RemoveAll(root)
err := os.MkdirAll(root, 0700)
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(root)
srv := startTestServer(config)
defer srv.Shutdown()
usersCl := client.NewSingleUserClient(addr)
if !waitForReady(addr) {
t.Fatal("fail to start server")
}
t.Run("test users APIs: Login-SetPwd-Logout-Login", func(t *testing.T) {
resp, _, errs := usersCl.Login(adminName, adminPwd)
if len(errs) > 0 {
t.Fatal(errs)
} else if resp.StatusCode != 200 {
t.Fatal(resp.StatusCode)
}
token := client.GetCookie(resp.Cookies(), su.TokenCookie)
resp, _, errs = usersCl.SetPwd(adminPwd, adminNewPwd, token)
if len(errs) > 0 {
t.Fatal(errs)
} else if resp.StatusCode != 200 {
t.Fatal(resp.StatusCode)
}
resp, _, errs = usersCl.Logout(token)
if len(errs) > 0 {
t.Fatal(errs)
} else if resp.StatusCode != 200 {
t.Fatal(resp.StatusCode)
}
resp, _, errs = usersCl.Login(adminName, adminNewPwd)
if len(errs) > 0 {
t.Fatal(errs)
} else if resp.StatusCode != 200 {
t.Fatal(resp.StatusCode)
}
})
t.Run("test users APIs: Login-AddUser-Logout-Login", func(t *testing.T) {
resp, _, errs := usersCl.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)
userName, userPwd := "user", "1234"
resp, auResp, errs := usersCl.AddUser(userName, userPwd, userstore.UserRole, token)
if len(errs) > 0 {
t.Fatal(errs)
} else if resp.StatusCode != 200 {
t.Fatal(resp.StatusCode)
}
// TODO: check id
fmt.Printf("new user id: %v\n", auResp)
resp, _, errs = usersCl.Logout(token)
if len(errs) > 0 {
t.Fatal(errs)
} else if resp.StatusCode != 200 {
t.Fatal(resp.StatusCode)
}
resp, _, errs = usersCl.Login(userName, userPwd)
if len(errs) > 0 {
t.Fatal(errs)
} else if resp.StatusCode != 200 {
t.Fatal(resp.StatusCode)
}
})
}