moto/internal/user/passport/login.go

109 lines
2.4 KiB
Go

package passport
import (
"context"
"fmt"
"git.nobla.cn/golang/kos/pkg/cache"
"git.nobla.cn/golang/moto/common/db"
"git.nobla.cn/golang/moto/internal/user/types"
"git.nobla.cn/golang/moto/models"
"github.com/mssola/useragent"
"strings"
"sync"
"time"
)
var (
tokenizeLocker sync.RWMutex
tokenizes map[string]*types.Tokenize
LoginMaxTires = 5
)
func init() {
tokenizes = make(map[string]*types.Tokenize)
}
func Login(ctx context.Context, req *LoginRequest) (tk *types.Tokenize, err error) {
var (
tires int
duration time.Duration
)
tx := db.WithContext(ctx)
userModel := &models.User{}
if req.Remember {
duration = time.Hour * 24
} else {
duration = time.Hour * 2
}
cacheKey := fmt.Sprintf("passport:login:%s:attempts", req.RealIP)
if LoginMaxTires > 0 {
if err = cache.Load(ctx, cacheKey, &tires); err == nil {
if tires > LoginMaxTires {
err = ErrTooManyAttempts
return
}
}
}
if err = tx.Where("uid=?", req.Username).First(userModel).Error; err == nil {
if userModel.Password == req.Password || md5Hash(req.Password) == userModel.Password {
tk = types.NewTokenize(userModel.UID, duration)
tokenizeLocker.Lock()
tokenizes[tk.Token] = tk
tokenizeLocker.Unlock()
tk.Name = userModel.Username
ua := useragent.New(req.UserAgent)
loginModel := &models.Login{
UID: userModel.UID,
IP: req.RealIP,
Os: ua.OS(),
Platform: ua.Platform(),
AccessToken: tk.Token,
UserAgent: req.UserAgent,
}
browser, browserVersion := ua.Browser()
loginModel.Browser = browser + "/" + browserVersion
tx.Save(loginModel)
} else {
err = ErrInvalidPassword
_ = cache.StoreEx(ctx, cacheKey, tires+1, time.Minute*10)
}
} else {
_ = cache.StoreEx(ctx, cacheKey, tires+1, time.Minute*10)
}
return
}
func Validate(ctx context.Context, token string) (tk *types.Tokenize, err error) {
var (
ok bool
)
tokenizeLocker.Lock()
defer tokenizeLocker.Unlock()
token = strings.TrimSpace(token)
if token == "" {
return nil, ErrPermissionDenied
}
if tk, ok = tokenizes[token]; !ok {
return nil, ErrPermissionDenied
} else {
if tk.Validate() {
return tk, nil
} else {
delete(tokenizes, token)
return nil, ErrPermissionDenied
}
}
return
}
func Logout(ctx context.Context, token string) (ok bool) {
tokenizeLocker.Lock()
if _, ok = tokenizes[token]; ok {
delete(tokenizes, token)
}
tokenizeLocker.Unlock()
return
}