new features: Based on IP user registration restrictions
This commit is contained in:
parent
0fb92f380f
commit
ff2d3f85f3
@ -62,3 +62,5 @@ const SendIntervalKeyPrefix = "send:interval:"
|
|||||||
|
|
||||||
// SendCountLimitKeyPrefix Send Count Limit Key Prefix eg. send:limit:register:email:xxx@ppanel.dev
|
// SendCountLimitKeyPrefix Send Count Limit Key Prefix eg. send:limit:register:email:xxx@ppanel.dev
|
||||||
const SendCountLimitKeyPrefix = "send:limit:"
|
const SendCountLimitKeyPrefix = "send:limit:"
|
||||||
|
|
||||||
|
const RegisterIpKeyPrefix = "register:ip:"
|
||||||
|
|||||||
@ -71,6 +71,9 @@ func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginRequest) (resp *typ
|
|||||||
deviceInfo, err := l.svcCtx.UserModel.FindOneDeviceByIdentifier(l.ctx, req.Identifier)
|
deviceInfo, err := l.svcCtx.UserModel.FindOneDeviceByIdentifier(l.ctx, req.Identifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
if !registerIpLimit(l.svcCtx, l.ctx, req.IP, "device", req.Identifier) {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.RegisterIPLimit), "register ip limit: %v", req.IP)
|
||||||
|
}
|
||||||
// Device not found, create new user and device
|
// Device not found, create new user and device
|
||||||
userInfo, err = l.registerUserAndDevice(req)
|
userInfo, err = l.registerUserAndDevice(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
45
internal/logic/auth/registerLimitLogic.go
Normal file
45
internal/logic/auth/registerLimitLogic.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/perfect-panel/server/internal/config"
|
||||||
|
"github.com/perfect-panel/server/internal/svc"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func registerIpLimit(svcCtx *svc.ServiceContext, ctx context.Context, registerIp, authType, account string) (isOk bool) {
|
||||||
|
if !svcCtx.Config.Register.EnableIpRegisterLimit {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
cacheKey := fmt.Sprintf("%s%s:*", config.RegisterIpKeyPrefix, registerIp)
|
||||||
|
var cacheKeys []string
|
||||||
|
var cursor uint64
|
||||||
|
for {
|
||||||
|
keys, newCursor, err := svcCtx.Redis.Scan(ctx, 0, cacheKey, 100).Result()
|
||||||
|
if err != nil {
|
||||||
|
zap.S().Errorf("[registerIpLimit] Err: %v", err)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if len(keys) > 0 {
|
||||||
|
cacheKeys = append(cacheKeys, keys...)
|
||||||
|
}
|
||||||
|
cursor = newCursor
|
||||||
|
if cursor == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
key := fmt.Sprintf("%s%s:%s:%s", config.RegisterIpKeyPrefix, registerIp, authType, account)
|
||||||
|
if err := svcCtx.Redis.Set(ctx, key, account, time.Minute*time.Duration(svcCtx.Config.Register.IpRegisterLimitDuration)).Err(); err != nil {
|
||||||
|
zap.S().Errorf("[registerIpLimit] Set Err: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if len(cacheKeys) < int(svcCtx.Config.Register.IpRegisterLimit) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
@ -102,7 +102,9 @@ func (l *TelephoneUserRegisterLogic) TelephoneUserRegister(req *types.TelephoneR
|
|||||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InviteCodeError), "invite code is invalid")
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InviteCodeError), "invite code is invalid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !registerIpLimit(l.svcCtx, l.ctx, req.IP, "mobile", phoneNumber) {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.RegisterIPLimit), "register ip limit: %v", req.IP)
|
||||||
|
}
|
||||||
// Generate password
|
// Generate password
|
||||||
pwd := tool.EncodePassWord(req.Password)
|
pwd := tool.EncodePassWord(req.Password)
|
||||||
userInfo := &user.User{
|
userInfo := &user.User{
|
||||||
|
|||||||
@ -86,6 +86,11 @@ func (l *UserRegisterLogic) UserRegister(req *types.UserRegisterRequest) (resp *
|
|||||||
} else if err == nil {
|
} else if err == nil {
|
||||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserExist), "user email exist: %v", req.Email)
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserExist), "user email exist: %v", req.Email)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !registerIpLimit(l.svcCtx, l.ctx, req.IP, "email", req.Email) {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.RegisterIPLimit), "register ip limit: %v", req.IP)
|
||||||
|
}
|
||||||
|
|
||||||
// Generate password
|
// Generate password
|
||||||
pwd := tool.EncodePassWord(req.Password)
|
pwd := tool.EncodePassWord(req.Password)
|
||||||
userInfo := &user.User{
|
userInfo := &user.User{
|
||||||
|
|||||||
@ -27,6 +27,7 @@ const (
|
|||||||
TelegramNotBound uint32 = 20007
|
TelegramNotBound uint32 = 20007
|
||||||
UserNotBindOauth uint32 = 20008
|
UserNotBindOauth uint32 = 20008
|
||||||
InviteCodeError uint32 = 20009
|
InviteCodeError uint32 = 20009
|
||||||
|
RegisterIPLimit uint32 = 20010
|
||||||
)
|
)
|
||||||
|
|
||||||
// Node error
|
// Node error
|
||||||
|
|||||||
@ -33,6 +33,7 @@ func init() {
|
|||||||
TelegramNotBound: "Telegram not bound ",
|
TelegramNotBound: "Telegram not bound ",
|
||||||
UserNotBindOauth: "User not bind oauth method",
|
UserNotBindOauth: "User not bind oauth method",
|
||||||
InviteCodeError: "Invite code error",
|
InviteCodeError: "Invite code error",
|
||||||
|
RegisterIPLimit: "Too many registrations",
|
||||||
|
|
||||||
// Node error
|
// Node error
|
||||||
NodeExist: "Node already exists",
|
NodeExist: "Node already exists",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user