chore(single_user): delete single user handlers
This commit is contained in:
parent
d0a8a6d43a
commit
cb478ca266
2 changed files with 0 additions and 303 deletions
|
@ -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
|
|
||||||
}
|
|
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue