修复 「1.2.2 用户管理-用户列表勾选单一用户会全选 」 close #216

This commit is contained in:
dushixiang
2022-01-23 17:53:22 +08:00
parent 29c066ca3a
commit d35b348a33
130 changed files with 5467 additions and 4554 deletions

View File

@ -1,58 +1,34 @@
package api
import (
"next-terminal/server/constant"
"context"
"path"
"strconv"
"strings"
"time"
"next-terminal/server/config"
"next-terminal/server/constant"
"next-terminal/server/dto"
"next-terminal/server/global/cache"
"next-terminal/server/model"
"next-terminal/server/repository"
"next-terminal/server/service"
"next-terminal/server/totp"
"next-terminal/server/utils"
"github.com/labstack/echo/v4"
)
const (
RememberEffectiveTime = time.Hour * time.Duration(24*14)
NotRememberEffectiveTime = time.Hour * time.Duration(2)
)
type AccountApi struct{}
type LoginAccount struct {
Username string `json:"username"`
Password string `json:"password"`
Remember bool `json:"remember"`
TOTP string `json:"totp"`
}
type ConfirmTOTP struct {
Secret string `json:"secret"`
TOTP string `json:"totp"`
}
type ChangePassword struct {
NewPassword string `json:"newPassword"`
OldPassword string `json:"oldPassword"`
}
type Authorization struct {
Token string
Remember bool
User model.User
}
func LoginEndpoint(c echo.Context) error {
var loginAccount LoginAccount
func (api AccountApi) LoginEndpoint(c echo.Context) error {
var loginAccount dto.LoginAccount
if err := c.Bind(&loginAccount); err != nil {
return err
}
// 存储登录失败次数信息
loginFailCountKey := c.RealIP() + loginAccount.Username
v, ok := cache.GlobalCache.Get(loginFailCountKey)
v, ok := cache.LoginFailedKeyManager.Get(loginFailCountKey)
if !ok {
v = 1
}
@ -61,12 +37,12 @@ func LoginEndpoint(c echo.Context) error {
return Fail(c, -1, "登录失败次数过多请等待5分钟后再试")
}
user, err := userRepository.FindByUsername(loginAccount.Username)
user, err := repository.UserRepository.FindByUsername(context.TODO(), loginAccount.Username)
if err != nil {
count++
cache.GlobalCache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
cache.LoginFailedKeyManager.Set(loginFailCountKey, count, cache.LoginLockExpiration)
// 保存登录日志
if err := SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, false, loginAccount.Remember, "", "账号或密码不正确"); err != nil {
if err := service.UserService.SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, false, loginAccount.Remember, "", "账号或密码不正确"); err != nil {
return err
}
return FailWithData(c, -1, "您输入的账号或密码不正确", count)
@ -78,9 +54,9 @@ func LoginEndpoint(c echo.Context) error {
if err := utils.Encoder.Match([]byte(user.Password), []byte(loginAccount.Password)); err != nil {
count++
cache.GlobalCache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
cache.LoginFailedKeyManager.Set(loginFailCountKey, count, cache.LoginLockExpiration)
// 保存登录日志
if err := SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, false, loginAccount.Remember, "", "账号或密码不正确"); err != nil {
if err := service.UserService.SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, false, loginAccount.Remember, "", "账号或密码不正确"); err != nil {
return err
}
return FailWithData(c, -1, "您输入的账号或密码不正确", count)
@ -90,73 +66,49 @@ func LoginEndpoint(c echo.Context) error {
return Fail(c, 0, "")
}
token, err := LoginSuccess(loginAccount, user)
token, err := api.LoginSuccess(loginAccount, user)
if err != nil {
return err
}
// 保存登录日志
if err := SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, true, loginAccount.Remember, token, ""); err != nil {
if err := service.UserService.SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, true, loginAccount.Remember, token, ""); err != nil {
return err
}
return Success(c, token)
}
func SaveLoginLog(clientIP, clientUserAgent string, username string, success, remember bool, id, reason string) error {
loginLog := model.LoginLog{
Username: username,
ClientIP: clientIP,
ClientUserAgent: clientUserAgent,
LoginTime: utils.NowJsonTime(),
Reason: reason,
Remember: remember,
}
if success {
loginLog.State = "1"
loginLog.ID = id
} else {
loginLog.State = "0"
loginLog.ID = utils.UUID()
}
func (api AccountApi) LoginSuccess(loginAccount dto.LoginAccount, user model.User) (string, error) {
token := utils.LongUUID()
if err := loginLogRepository.Create(&loginLog); err != nil {
return err
}
return nil
}
func LoginSuccess(loginAccount LoginAccount, user model.User) (token string, err error) {
token = strings.Join([]string{utils.UUID(), utils.UUID(), utils.UUID(), utils.UUID()}, "")
authorization := Authorization{
authorization := dto.Authorization{
Token: token,
Type: constant.LoginToken,
Remember: loginAccount.Remember,
User: user,
User: &user,
}
cacheKey := userService.BuildCacheKeyByToken(token)
if authorization.Remember {
// 记住登录有效期两周
cache.GlobalCache.Set(cacheKey, authorization, RememberEffectiveTime)
cache.TokenManager.Set(token, authorization, cache.RememberMeExpiration)
} else {
cache.GlobalCache.Set(cacheKey, authorization, NotRememberEffectiveTime)
cache.TokenManager.Set(token, authorization, cache.NotRememberExpiration)
}
// 修改登录状态
err = userRepository.Update(&model.User{Online: true, ID: user.ID})
err := repository.UserRepository.Update(context.TODO(), &model.User{Online: true, ID: user.ID})
return token, err
}
func loginWithTotpEndpoint(c echo.Context) error {
var loginAccount LoginAccount
func (api AccountApi) LoginWithTotpEndpoint(c echo.Context) error {
var loginAccount dto.LoginAccount
if err := c.Bind(&loginAccount); err != nil {
return err
}
// 存储登录失败次数信息
loginFailCountKey := c.RealIP() + loginAccount.Username
v, ok := cache.GlobalCache.Get(loginFailCountKey)
v, ok := cache.LoginFailedKeyManager.Get(loginFailCountKey)
if !ok {
v = 1
}
@ -165,12 +117,12 @@ func loginWithTotpEndpoint(c echo.Context) error {
return Fail(c, -1, "登录失败次数过多请等待5分钟后再试")
}
user, err := userRepository.FindByUsername(loginAccount.Username)
user, err := repository.UserRepository.FindByUsername(context.TODO(), loginAccount.Username)
if err != nil {
count++
cache.GlobalCache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
cache.LoginFailedKeyManager.Set(loginFailCountKey, count, cache.LoginLockExpiration)
// 保存登录日志
if err := SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, false, loginAccount.Remember, "", "账号或密码不正确"); err != nil {
if err := service.UserService.SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, false, loginAccount.Remember, "", "账号或密码不正确"); err != nil {
return err
}
return FailWithData(c, -1, "您输入的账号或密码不正确", count)
@ -182,9 +134,9 @@ func loginWithTotpEndpoint(c echo.Context) error {
if err := utils.Encoder.Match([]byte(user.Password), []byte(loginAccount.Password)); err != nil {
count++
cache.GlobalCache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
cache.LoginFailedKeyManager.Set(loginFailCountKey, count, cache.LoginLockExpiration)
// 保存登录日志
if err := SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, false, loginAccount.Remember, "", "账号或密码不正确"); err != nil {
if err := service.UserService.SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, false, loginAccount.Remember, "", "账号或密码不正确"); err != nil {
return err
}
return FailWithData(c, -1, "您输入的账号或密码不正确", count)
@ -192,42 +144,42 @@ func loginWithTotpEndpoint(c echo.Context) error {
if !totp.Validate(loginAccount.TOTP, user.TOTPSecret) {
count++
cache.GlobalCache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
cache.LoginFailedKeyManager.Set(loginFailCountKey, count, cache.LoginLockExpiration)
// 保存登录日志
if err := SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, false, loginAccount.Remember, "", "双因素认证授权码不正确"); err != nil {
if err := service.UserService.SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, false, loginAccount.Remember, "", "双因素认证授权码不正确"); err != nil {
return err
}
return FailWithData(c, -1, "您输入双因素认证授权码不正确", count)
}
token, err := LoginSuccess(loginAccount, user)
token, err := api.LoginSuccess(loginAccount, user)
if err != nil {
return err
}
// 保存登录日志
if err := SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, true, loginAccount.Remember, token, ""); err != nil {
if err := service.UserService.SaveLoginLog(c.RealIP(), c.Request().UserAgent(), loginAccount.Username, true, loginAccount.Remember, token, ""); err != nil {
return err
}
return Success(c, token)
}
func LogoutEndpoint(c echo.Context) error {
func (api AccountApi) LogoutEndpoint(c echo.Context) error {
token := GetToken(c)
err := userService.LogoutByToken(token)
err := service.UserService.LogoutByToken(token)
if err != nil {
return err
}
return Success(c, nil)
}
func ConfirmTOTPEndpoint(c echo.Context) error {
func (api AccountApi) ConfirmTOTPEndpoint(c echo.Context) error {
if config.GlobalCfg.Demo {
return Fail(c, 0, "演示模式禁止开启两步验证")
}
account, _ := GetCurrentAccount(c)
var confirmTOTP ConfirmTOTP
var confirmTOTP dto.ConfirmTOTP
if err := c.Bind(&confirmTOTP); err != nil {
return err
}
@ -241,14 +193,14 @@ func ConfirmTOTPEndpoint(c echo.Context) error {
ID: account.ID,
}
if err := userRepository.Update(u); err != nil {
if err := repository.UserRepository.Update(context.TODO(), u); err != nil {
return err
}
return Success(c, nil)
}
func ReloadTOTPEndpoint(c echo.Context) error {
func (api AccountApi) ReloadTOTPEndpoint(c echo.Context) error {
account, _ := GetCurrentAccount(c)
key, err := totp.NewTOTP(totp.GenerateOpts{
@ -275,25 +227,25 @@ func ReloadTOTPEndpoint(c echo.Context) error {
})
}
func ResetTOTPEndpoint(c echo.Context) error {
func (api AccountApi) ResetTOTPEndpoint(c echo.Context) error {
account, _ := GetCurrentAccount(c)
u := &model.User{
TOTPSecret: "-",
ID: account.ID,
}
if err := userRepository.Update(u); err != nil {
if err := repository.UserRepository.Update(context.TODO(), u); err != nil {
return err
}
return Success(c, "")
}
func ChangePasswordEndpoint(c echo.Context) error {
func (api AccountApi) ChangePasswordEndpoint(c echo.Context) error {
if config.GlobalCfg.Demo {
return Fail(c, 0, "演示模式禁止修改密码")
}
account, _ := GetCurrentAccount(c)
var changePassword ChangePassword
var changePassword dto.ChangePassword
if err := c.Bind(&changePassword); err != nil {
return err
}
@ -311,11 +263,11 @@ func ChangePasswordEndpoint(c echo.Context) error {
ID: account.ID,
}
if err := userRepository.Update(u); err != nil {
if err := repository.UserRepository.Update(context.TODO(), u); err != nil {
return err
}
return LogoutEndpoint(c)
return api.LogoutEndpoint(c)
}
type AccountInfo struct {
@ -326,10 +278,10 @@ type AccountInfo struct {
EnableTotp bool `json:"enableTotp"`
}
func InfoEndpoint(c echo.Context) error {
func (api AccountApi) InfoEndpoint(c echo.Context) error {
account, _ := GetCurrentAccount(c)
user, err := userRepository.FindById(account.ID)
user, err := repository.UserRepository.FindById(context.TODO(), account.ID)
if err != nil {
return err
}
@ -344,7 +296,7 @@ func InfoEndpoint(c echo.Context) error {
return Success(c, info)
}
func AccountAssetEndpoint(c echo.Context) error {
func (api AccountApi) AccountAssetEndpoint(c echo.Context) error {
pageIndex, _ := strconv.Atoi(c.QueryParam("pageIndex"))
pageSize, _ := strconv.Atoi(c.QueryParam("pageSize"))
name := c.QueryParam("name")
@ -359,26 +311,26 @@ func AccountAssetEndpoint(c echo.Context) error {
field := c.QueryParam("field")
account, _ := GetCurrentAccount(c)
items, total, err := assetRepository.Find(pageIndex, pageSize, name, protocol, tags, account, owner, sharer, userGroupId, ip, order, field)
items, total, err := repository.AssetRepository.Find(context.TODO(), pageIndex, pageSize, name, protocol, tags, account, owner, sharer, userGroupId, ip, order, field)
if err != nil {
return err
}
return Success(c, H{
return Success(c, Map{
"total": total,
"items": items,
})
}
func AccountStorageEndpoint(c echo.Context) error {
func (api AccountApi) AccountStorageEndpoint(c echo.Context) error {
account, _ := GetCurrentAccount(c)
storageId := account.ID
storage, err := storageRepository.FindById(storageId)
storage, err := repository.StorageRepository.FindById(context.TODO(), storageId)
if err != nil {
return err
}
structMap := utils.StructToMap(storage)
drivePath := storageService.GetBaseDrivePath()
drivePath := service.StorageService.GetBaseDrivePath()
dirSize, err := utils.DirSize(path.Join(drivePath, storageId))
if err != nil {
structMap["usedSize"] = -1
@ -388,3 +340,20 @@ func AccountStorageEndpoint(c echo.Context) error {
return Success(c, structMap)
}
func (api AccountApi) AccessTokenGetEndpoint(c echo.Context) error {
account, _ := GetCurrentAccount(c)
accessToken, err := repository.AccessTokenRepository.FindByUserId(context.TODO(), account.ID)
if err != nil {
return err
}
return Success(c, accessToken)
}
func (api AccountApi) AccessTokenGenEndpoint(c echo.Context) error {
account, _ := GetCurrentAccount(c)
if err := service.AccessTokenService.GenAccessToken(account.ID); err != nil {
return err
}
return Success(c, nil)
}