🎨 新增ip检测配置功能
This commit is contained in:
@@ -55,7 +55,7 @@ func (*AppUserApi) Login(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
user, err := appUserService.Login(p)
|
||||
user, isNewUser, err := appUserService.Login(p)
|
||||
if err != nil {
|
||||
r.FailWithMessage("登录失败", ctx)
|
||||
return
|
||||
@@ -104,6 +104,7 @@ func (*AppUserApi) Login(ctx *gin.Context) {
|
||||
"User": user,
|
||||
"Token": token,
|
||||
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
||||
"IsNewUser": isNewUser,
|
||||
}, "登录成功", ctx)
|
||||
} else if err != nil {
|
||||
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
|
||||
@@ -127,7 +128,7 @@ func (*AppUserApi) WechatLogin(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
user, err := appUserService.WechatLogin(info)
|
||||
user, isNewUser, err := appUserService.WechatLogin(info)
|
||||
if err != nil {
|
||||
r.FailWithMessage("登录失败:"+err.Error(), ctx)
|
||||
return
|
||||
@@ -158,6 +159,16 @@ func (*AppUserApi) WechatLogin(ctx *gin.Context) {
|
||||
}
|
||||
}()
|
||||
|
||||
// 判断是否为新用户
|
||||
if isNewUser {
|
||||
ipCheckStatus := false
|
||||
|
||||
err = global.GVA_DB.Model(&user2.IpCheck{}).Select("status").Scan(&ipCheckStatus).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取IP检测状态失败", zap.Error(err))
|
||||
}
|
||||
|
||||
if ipCheckStatus {
|
||||
adcodes := utils.CheckIPInAdcodes(loginLog.Address)
|
||||
if !adcodes {
|
||||
global.GVA_LOG.Warn("异常登录地址", zap.String("address", loginLog.Address), zap.Uint("userId", user.ID))
|
||||
@@ -170,6 +181,8 @@ func (*AppUserApi) WechatLogin(ctx *gin.Context) {
|
||||
r.Banned("用户已被禁用", ctx)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 生成token
|
||||
token, claims, err := user_jwt.LoginToken(user)
|
||||
@@ -195,6 +208,7 @@ func (*AppUserApi) WechatLogin(ctx *gin.Context) {
|
||||
"User": user,
|
||||
"Token": token,
|
||||
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
||||
"IsNewUser": isNewUser,
|
||||
}, "登录成功", ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"git.echol.cn/loser/lckt/model/app"
|
||||
common "git.echol.cn/loser/lckt/model/common/request"
|
||||
r "git.echol.cn/loser/lckt/model/common/response"
|
||||
"git.echol.cn/loser/lckt/model/user"
|
||||
"git.echol.cn/loser/lckt/model/user/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
@@ -272,3 +273,57 @@ func (a *UserApi) SetTeacherExpectRate(context *gin.Context) {
|
||||
r.OkWithMessage("修改讲师信息成功", context)
|
||||
|
||||
}
|
||||
|
||||
// ===========================IP检测配置==========================
|
||||
|
||||
// SetIpCheckConfig 设置IP检测配置
|
||||
func (a *UserApi) SetIpCheckConfig(ctx *gin.Context) {
|
||||
var p user.IpCheck
|
||||
if err := ctx.ShouldBind(&p); err != nil {
|
||||
r.FailWithMessage(err.Error(), ctx)
|
||||
global.GVA_LOG.Error("参数错误,设置IP检测配置失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
config, err := userService.SetIpConfig(p)
|
||||
if err != nil {
|
||||
r.FailWithMessage("设置IP检测配置失败", ctx)
|
||||
return
|
||||
}
|
||||
r.OkWithData(config, ctx)
|
||||
}
|
||||
|
||||
// GetIpCheckConfig 获取IP检测配置
|
||||
func (a *UserApi) GetIpCheckConfig(ctx *gin.Context) {
|
||||
config, err := userService.GetIpConfig()
|
||||
if err != nil {
|
||||
r.FailWithMessage("获取IP检测配置失败", ctx)
|
||||
return
|
||||
}
|
||||
r.OkWithData(config, ctx)
|
||||
}
|
||||
|
||||
// GetIpCheckStatus 获取IP检测状态
|
||||
func (a *UserApi) GetIpCheckStatus(ctx *gin.Context) {
|
||||
status, err := userService.GetIpStatus()
|
||||
if err != nil {
|
||||
r.FailWithMessage("获取IP检测状态失败", ctx)
|
||||
return
|
||||
}
|
||||
r.OkWithDetailed(status, "获取IP检测状态成功", ctx)
|
||||
}
|
||||
|
||||
// SetIpCheckStatus 设置IP检测状态
|
||||
func (a *UserApi) SetIpCheckStatus(ctx *gin.Context) {
|
||||
var p user.IpCheck
|
||||
if err := ctx.ShouldBind(&p); err != nil {
|
||||
r.FailWithMessage(err.Error(), ctx)
|
||||
global.GVA_LOG.Error("参数错误,设置IP检测状态失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
status, err := userService.SetIpStatus(p.Status)
|
||||
if err != nil {
|
||||
r.FailWithMessage("设置IP检测状态失败", ctx)
|
||||
return
|
||||
}
|
||||
r.OkWithDetailed(status, "设置IP检测状态成功", ctx)
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ func RegisterTables() {
|
||||
app.BalanceLog{},
|
||||
app.With{},
|
||||
app.Domain{},
|
||||
user.IpCheck{},
|
||||
)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("register table failed", zap.Error(err))
|
||||
|
||||
@@ -11,3 +11,11 @@ type UpdateTeacherVipPriceBatch struct {
|
||||
Ids []uint `json:"ids" form:"ids" vd:"@:len($)>0; msg:'请选择要修改的讲师VIP'"`
|
||||
Price float64 `json:"price" form:"price" vd:"@:len($)>0; msg:'请输入讲师VIP价格'"` // 讲师VIP价格
|
||||
}
|
||||
|
||||
type IpCheckConfigReq struct {
|
||||
IpAddrs []string `json:"ip_addrs" form:"ip_addrs" vd:"@:len($)>0; msg:'请输入要检测的IP地址列表'"` // IP地址列表
|
||||
}
|
||||
|
||||
type IpCheckStatus struct {
|
||||
Status bool `json:"status" form:"status"`
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ type UserRouter struct{}
|
||||
// InitUserRouter 初始化 用户相关 路由信息
|
||||
func (s *UserRouter) InitUserRouter(Router *gin.RouterGroup, PublicRouter *gin.RouterGroup) {
|
||||
userRouter := Router.Group("app_user").Use(middleware.OperationRecord())
|
||||
publicRouter := PublicRouter.Group("app_user")
|
||||
{
|
||||
userRouter.GET("list", userApi.GetUserList) // 获取用户列表
|
||||
userRouter.PUT("setBalance", userApi.SetBalance) // 更新用户余额
|
||||
@@ -34,4 +35,12 @@ func (s *UserRouter) InitUserRouter(Router *gin.RouterGroup, PublicRouter *gin.R
|
||||
userRouter.DELETE("teacher_vip", teacherVipApi.DeleteTeacherVip) // 删除讲师VIP
|
||||
userRouter.PUT("/teacher_vip/price", teacherVipApi.UpdatePriceBatch) // 批量设置讲师课程价格
|
||||
}
|
||||
|
||||
{
|
||||
userRouter.PUT("ipStatus", userApi.SetIpCheckStatus) // 设置ip检测状态
|
||||
userRouter.PUT("ipCon", userApi.SetIpCheckConfig) // 设置ip检测配置
|
||||
publicRouter.GET("ipCon", userApi.GetIpCheckConfig) // 获取ip检测配置
|
||||
userRouter.GET("ipStatus", userApi.GetIpCheckStatus) // 获取ip检测状态
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ import (
|
||||
type AppUserService struct{}
|
||||
|
||||
// Login 用户登录
|
||||
func (u *AppUserService) Login(req request.CodeLoginReq) (users user.User, err error) {
|
||||
func (u *AppUserService) Login(req request.CodeLoginReq) (users user.User, isNewUser bool, err error) {
|
||||
isNewUser = false
|
||||
// 1. 判断用户是否存在
|
||||
var count int64
|
||||
err = global.GVA_DB.Model(&user.User{}).Where("phone = ?", req.Phone).Count(&count).Error
|
||||
@@ -30,6 +31,7 @@ func (u *AppUserService) Login(req request.CodeLoginReq) (users user.User, err e
|
||||
|
||||
// 2. 如果用户不存在,则创建用户
|
||||
if count == 0 {
|
||||
isNewUser = true
|
||||
user := user.User{
|
||||
Phone: req.Phone,
|
||||
UserLabel: 1,
|
||||
@@ -51,7 +53,8 @@ func (u *AppUserService) Login(req request.CodeLoginReq) (users user.User, err e
|
||||
}
|
||||
|
||||
// WechatLogin 微信登录
|
||||
func (u *AppUserService) WechatLogin(info *providers.User) (users user.User, err error) {
|
||||
func (u *AppUserService) WechatLogin(info *providers.User) (users user.User, isNewUser bool, err error) {
|
||||
isNewUser = false
|
||||
openID := info.GetOpenID()
|
||||
var count int64
|
||||
if openID == "" {
|
||||
@@ -76,7 +79,7 @@ func (u *AppUserService) WechatLogin(info *providers.User) (users user.User, err
|
||||
global.GVA_LOG.Error("创建用户失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
return newUser, nil
|
||||
return newUser, true, nil
|
||||
} else {
|
||||
err = global.GVA_DB.Where("open_id = ?", openID).First(&users).Error
|
||||
if err != nil {
|
||||
|
||||
@@ -392,3 +392,51 @@ func (u *UserService) SetTeacherExpectRate(p request.SetTeacherInfo) (err error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (u *UserService) SetIpConfig(p user.IpCheck) (user.IpCheck, error) {
|
||||
p.ID = 1
|
||||
err := global.GVA_DB.Save(&p).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("修改IP检测配置失败", zap.Error(err))
|
||||
return p, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (u *UserService) GetIpConfig() (ipConfig user.IpCheck, err error) {
|
||||
ipConfig.ID = 1
|
||||
err = global.GVA_DB.First(&ipConfig).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取IP检测配置失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (u *UserService) SetIpStatus(status bool) (bool, error) {
|
||||
var ipConfig user.IpCheck
|
||||
ipConfig.ID = 1
|
||||
err := global.GVA_DB.First(&ipConfig).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取IP检测配置失败", zap.Error(err))
|
||||
return false, err
|
||||
}
|
||||
ipConfig.Status = status
|
||||
err = global.GVA_DB.Save(&ipConfig).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("修改IP检测状态失败", zap.Error(err))
|
||||
return false, err
|
||||
}
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func (u *UserService) GetIpStatus() (status bool, err error) {
|
||||
var ipConfig user.IpCheck
|
||||
err = global.GVA_DB.Where("id = 1").First(&ipConfig).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取IP检测配置失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
status = ipConfig.Status
|
||||
return
|
||||
}
|
||||
|
||||
31
utils/ip.go
31
utils/ip.go
@@ -3,6 +3,9 @@ package utils
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.echol.cn/loser/lckt/global"
|
||||
user2 "git.echol.cn/loser/lckt/model/user"
|
||||
"go.uber.org/zap"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -14,13 +17,6 @@ type ipAdcodeResp struct {
|
||||
} `json:"adcode"`
|
||||
}
|
||||
|
||||
// adcodes 是允许的地区编码列表
|
||||
var adcodes = []string{
|
||||
"重庆",
|
||||
"海南",
|
||||
"广东",
|
||||
}
|
||||
|
||||
func GetIPAdcode(ip string) string {
|
||||
url := fmt.Sprintf("https://api.vore.top/api/IPdata?ip=%s", ip)
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
@@ -38,6 +34,27 @@ func GetIPAdcode(ip string) string {
|
||||
|
||||
// CheckIPInAdcodes 检测用户IP是否在指定的地区编码范围内
|
||||
func CheckIPInAdcodes(ipAdcode string) bool {
|
||||
// 查询IP配置
|
||||
ipCon := user2.IpCheck{}
|
||||
err := global.GVA_DB.First(&ipCon).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取IP配置失败", zap.Error(err))
|
||||
return false
|
||||
}
|
||||
// 如果IP检测未启用,直接返回true
|
||||
if !ipCon.Status {
|
||||
return true
|
||||
}
|
||||
// 解析允许的地区编码列表
|
||||
var adcodes []string
|
||||
// 通过逗号分隔
|
||||
for _, code := range strings.Split(ipCon.Addrs, ",") {
|
||||
trimmed := strings.TrimSpace(code)
|
||||
if trimmed != "" {
|
||||
adcodes = append(adcodes, trimmed)
|
||||
}
|
||||
}
|
||||
|
||||
lower := strings.ToLower(ipAdcode)
|
||||
for _, code := range adcodes {
|
||||
// 检测是否包含
|
||||
|
||||
Reference in New Issue
Block a user