chore(single_user): delete single user handlers

This commit is contained in:
hexxa 2022-08-26 20:02:27 +08:00 committed by Hexxa
parent d0a8a6d43a
commit cb478ca266
2 changed files with 0 additions and 303 deletions

View file

@ -1,219 +0,0 @@
package singleuserhdr
import (
"errors"
"fmt"
"time"
"github.com/gin-gonic/gin"
"github.com/ihexxa/gocfg"
"golang.org/x/crypto/bcrypt"
"github.com/ihexxa/quickshare/src/depidx"
q "github.com/ihexxa/quickshare/src/handlers"
)
var (
ErrInvalidUser = errors.New("invalid user name or password")
ErrInvalidConfig = errors.New("invalid user config")
UserParam = "user"
PwdParam = "pwd"
NewPwdParam = "newpwd"
RoleParam = "role"
ExpireParam = "expire"
InitTimeParam = "initTime"
TokenCookie = "tk"
AdminRole = "admin"
VisitorRole = "visitor"
InitNs = "usersInit"
UsersNs = "users"
RolesNs = "roles"
)
type SimpleUserHandlers struct {
cfg gocfg.ICfg
deps *depidx.Deps
}
func NewSimpleUserHandlers(cfg gocfg.ICfg, deps *depidx.Deps) (*SimpleUserHandlers, error) {
var err error
if err = deps.KV().AddNamespace(InitNs); err != nil {
return nil, err
}
if err = deps.KV().AddNamespace(UsersNs); err != nil {
return nil, err
}
if err = deps.KV().AddNamespace(RolesNs); err != nil {
return nil, err
}
return &SimpleUserHandlers{
cfg: cfg,
deps: deps,
}, nil
}
func (h *SimpleUserHandlers) IsInited() bool {
_, ok := h.deps.KV().GetStringIn(InitNs, InitTimeParam)
return ok
}
func (h *SimpleUserHandlers) Init(userName, pwd string) (string, error) {
if userName == "" {
return "", errors.New("user name can not be empty")
}
pwdHash, err := bcrypt.GenerateFromPassword([]byte(pwd), 10)
if err != nil {
return "", err
}
err = h.deps.KV().SetStringIn(UsersNs, userName, string(pwdHash))
if err != nil {
return "", err
}
err = h.deps.KV().SetStringIn(RolesNs, userName, AdminRole)
if err != nil {
return "", err
}
err = h.deps.KV().SetStringIn(InitNs, InitTimeParam, fmt.Sprintf("%d", time.Now().Unix()))
if err != nil {
return "", err
}
return pwd, nil
}
type LoginReq struct {
User string `json:"user"`
Pwd string `json:"pwd"`
}
func (h *SimpleUserHandlers) checkPwd(user, pwd string) error {
expectedHash, ok := h.deps.KV().GetStringIn(UsersNs, user)
if !ok {
return ErrInvalidConfig
}
return bcrypt.CompareHashAndPassword([]byte(expectedHash), []byte(pwd))
}
func (h *SimpleUserHandlers) Login(c *gin.Context) {
req := &LoginReq{}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(q.ErrResp(c, 500, err))
return
}
if err := h.checkPwd(req.User, req.Pwd); err != nil {
c.JSON(q.ErrResp(c, 500, err))
return
}
role, ok := h.deps.KV().GetStringIn(RolesNs, req.User)
if !ok {
c.JSON(q.ErrResp(c, 501, ErrInvalidConfig))
return
}
ttl := h.cfg.GrabInt("Users.CookieTTL")
token, err := h.deps.Token().ToToken(map[string]string{
UserParam: req.User,
RoleParam: role,
ExpireParam: fmt.Sprintf("%d", time.Now().Unix()+int64(ttl)),
})
if err != nil {
c.JSON(q.ErrResp(c, 500, err))
return
}
secure := h.cfg.GrabBool("Users.CookieSecure")
httpOnly := h.cfg.GrabBool("Users.CookieHttpOnly")
c.SetCookie(TokenCookie, token, ttl, "/", "", secure, httpOnly)
c.JSON(q.Resp(200))
}
type LogoutReq struct {
}
func (h *SimpleUserHandlers) Logout(c *gin.Context) {
// token alreay verified in the authn middleware
secure := h.cfg.GrabBool("Users.CookieSecure")
httpOnly := h.cfg.GrabBool("Users.CookieHttpOnly")
c.SetCookie(TokenCookie, "", 0, "/", "", secure, httpOnly)
c.JSON(q.Resp(200))
}
func (h *SimpleUserHandlers) IsAuthed(c *gin.Context) {
// token alreay verified in the authn middleware
c.JSON(q.Resp(200))
}
type SetPwdReq struct {
OldPwd string `json:"oldPwd"`
NewPwd string `json:"newPwd"`
}
func (h *SimpleUserHandlers) SetPwd(c *gin.Context) {
req := &SetPwdReq{}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(q.ErrResp(c, 400, err))
return
} else if req.OldPwd == req.NewPwd {
c.JSON(q.ErrResp(c, 400, errors.New("password is not updated")))
return
}
claims, err := h.getUserInfo(c)
if err != nil {
c.JSON(q.ErrResp(c, 401, err))
return
}
expectedHash, ok := h.deps.KV().GetStringIn(UsersNs, claims[UserParam])
if !ok {
c.JSON(q.ErrResp(c, 500, ErrInvalidConfig))
return
}
err = bcrypt.CompareHashAndPassword([]byte(expectedHash), []byte(req.OldPwd))
if err != nil {
c.JSON(q.ErrResp(c, 401, ErrInvalidUser))
return
}
newHash, err := bcrypt.GenerateFromPassword([]byte(req.NewPwd), 10)
if err != nil {
c.JSON(q.ErrResp(c, 500, errors.New("fail to set password")))
return
}
err = h.deps.KV().SetStringIn(UsersNs, claims[UserParam], string(newHash))
if err != nil {
c.JSON(q.ErrResp(c, 500, ErrInvalidConfig))
return
}
c.JSON(q.Resp(200))
}
func (h *SimpleUserHandlers) getUserInfo(c *gin.Context) (map[string]string, error) {
tokenStr, err := c.Cookie(TokenCookie)
if err != nil {
return nil, err
}
claims, err := h.deps.Token().FromToken(
tokenStr,
map[string]string{
UserParam: "",
RoleParam: "",
ExpireParam: "",
},
)
if err != nil {
return nil, err
} else if claims[UserParam] == "" {
return nil, ErrInvalidConfig
}
return claims, nil
}

View file

@ -1,84 +0,0 @@
package singleuserhdr
import (
"errors"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
q "github.com/ihexxa/quickshare/src/handlers"
)
var exposedAPIs = map[string]bool{
"Login-fm": true,
"Health-fm": true,
}
var publicRootPath = "/"
var publicStaticPath = "/static"
func IsPublicPath(accessPath string) bool {
return accessPath == publicRootPath || strings.HasPrefix(accessPath, publicStaticPath)
}
func GetHandlerName(fullname string) (string, error) {
parts := strings.Split(fullname, ".")
if len(parts) == 0 {
return "", errors.New("invalid handler name")
}
return parts[len(parts)-1], nil
}
func (h *SimpleUserHandlers) Auth() gin.HandlerFunc {
return func(c *gin.Context) {
handlerName, err := GetHandlerName(c.HandlerName())
if err != nil {
c.JSON(q.ErrResp(c, 401, err))
return
}
accessPath := c.Request.URL.String()
enableAuth := h.cfg.GrabBool("Users.EnableAuth")
if enableAuth && !exposedAPIs[handlerName] && !IsPublicPath(accessPath) {
token, err := c.Cookie(TokenCookie)
if err != nil {
c.AbortWithStatusJSON(q.ErrResp(c, 401, err))
return
}
claims := map[string]string{
UserParam: "",
RoleParam: "",
ExpireParam: "",
}
claims, err = h.deps.Token().FromToken(token, claims)
if err != nil {
c.AbortWithStatusJSON(q.ErrResp(c, 401, err))
return
}
for key, val := range claims {
c.Set(key, val)
}
now := time.Now().Unix()
expire, err := strconv.ParseInt(claims[ExpireParam], 10, 64)
if err != nil || expire <= now {
c.AbortWithStatusJSON(q.ErrResp(c, 401, err))
return
}
// visitor is only allowed to download
if claims[RoleParam] != AdminRole && handlerName != "Download-fm" {
c.AbortWithStatusJSON(q.ErrResp(c, 401, errors.New("not allowed")))
return
}
} else {
// this is for UploadMgr to get user info to get related namespace
c.Set(UserParam, "quickshare_anonymous")
}
c.Next()
}
}