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 }