109 lines
2.4 KiB
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
|
|
}
|