package v1 import ( "aps_crm/conf" "aps_crm/constvar" "aps_crm/model" "aps_crm/model/request" "aps_crm/model/response" _ "aps_crm/model/response" "aps_crm/pkg/contextx" "aps_crm/pkg/convertx" "aps_crm/pkg/ecode" "aps_crm/pkg/encrypt" "aps_crm/pkg/logx" "aps_crm/pkg/snowflake" "aps_crm/utils" "fmt" "github.com/gin-gonic/gin" "github.com/go-redis/redis/v8" "github.com/mojocn/base64Captcha" "time" ) // 当开启多服务器部署时,替换下面的配置,使用redis共享存储验证码 // var store = captcha.NewDefaultRedisStore() var store = base64Captcha.DefaultMemStore // Login // @Tags Base // @Summary 用户登录 // @Produce application/json // @Param object body request.Login true "查询参数" // @Success 200 {object} contextx.Response{data=response.LoginResponse} "成功" // @Router /api/base/login [post] func (slf *BaseApi) Login(c *gin.Context) { var params request.Login ctx, ok := contextx.NewContext(c, ¶ms) if !ok { return } // 判断验证码是否开启 key := c.ClientIP() openCaptcha := conf.Conf.Captcha.OpenCaptcha // 是否开启防爆次数 openCaptchaTimeOut := conf.Conf.Captcha.OpenCaptchaTimeOut // 缓存超时时间 v, ok := constvar.BlackCache.Get(key) if !ok { constvar.BlackCache.Set(key, 1, time.Second*time.Duration(openCaptchaTimeOut)) } var oc bool = openCaptcha == 0 || convertx.InterfaceToInt(v) > openCaptcha // 0 表示每次登录都需要验证码 或者当前次数已超过防爆次数 if !oc || store.Verify(params.CaptchaId, params.Captcha, true) { u := &model.User{Username: params.Username, Password: params.Password} user, errCode := userService.Login(u) if errCode != ecode.OK { logx.Errorf("登陆失败! 用户名不存在或者密码错误! errCode:%v", errCode) // 验证码次数+1 _ = constvar.BlackCache.Increment(key, 1) ctx.Fail(errCode) return } if !user.Enable { logx.Errorf("登陆失败! 用户被禁止登录!") // 验证码次数+1 _ = constvar.BlackCache.Increment(key, 1) ctx.Fail(ecode.UserForbidden) return } // 赋值菜单ID列表 //user.MenuIds, _ = menuService.GetUserMenuIds(user.ID, user.UserType) slf.TokenNext(ctx, *user) return } // 验证码次数+1 _ = constvar.BlackCache.Increment(key, 1) ctx.Fail(ecode.CaptchaErr) } // TokenNext 登录以后签发jwt func (slf *BaseApi) TokenNext(ctx *contextx.Context, user model.User) { logx.Infof("TokenNext user:%+v", user) j := &utils.JWT{SigningKey: []byte(conf.Conf.JWT.SigningKey)} // 唯一签名 claims := j.CreateClaims(request.BaseClaims{ UserId: user.ID, Username: user.Username, ParentId: user.ParentName, UserType: user.UserType, }) token, err := j.CreateToken(claims) if err != nil { logx.Errorf("创建token失败! err:%v", err) ctx.Fail(ecode.CreateTokenErr) return } if !conf.Conf.System.UseMultipoint { // 不允许多点登录 ctx.OkWithDetailed(response.LoginResponse{ User: user, Token: token, //ExpiresAt: claims.StandardClaims.ExpiresAt * 1000, }) return } if jwtStr, err := jwtService.GetRedisJWT(user.Username); err == redis.Nil { // redis无JWT数据 if err := jwtService.SetRedisJWT(token, user.Username); err != nil { logx.Errorf("设置登录状态失败! err:%v", err) ctx.Fail(ecode.RedisErr) return } ctx.OkWithDetailed(response.LoginResponse{ User: user, Token: token, //ExpiresAt: claims.StandardClaims.ExpiresAt * 1000, }) } else if err != nil { // redis获取JWT报错 logx.Errorf("设置登录状态失败! err:%v", err) ctx.Fail(ecode.RedisErr) } else { // 成功获取redis的JWT,旧的作废 var blackJWT model.JwtBlacklist blackJWT.Jwt = jwtStr if err := jwtService.JsonInBlacklist(blackJWT); err != nil { ctx.Fail(ecode.DBErr) return } if err := jwtService.SetRedisJWT(token, user.Username); err != nil { ctx.Fail(ecode.RedisErr) return } ctx.OkWithDetailed(response.LoginResponse{ User: user, Token: token, //ExpiresAt: claims.StandardClaims.ExpiresAt * 1000, }) } } // Register // @Tags User // @Summary 注册账号 // @Produce application/json // @Param object body request.Register true "查询参数" // @Success 200 {object} contextx.Response{data=response.UserResponse} "成功" // @Router /api/user/register [post] func (slf *BaseApi) Register(c *gin.Context) { var params request.Register ctx, ok := contextx.NewContext(c, ¶ms) if !ok { return } userInfo := utils.GetUserInfo(c) if len(userInfo.UserId) <= 0 { ctx.Fail(ecode.UnknownErr) return } if len(params.Username) == 0 || len(params.Password) == 0 || len(params.Phone) == 0 || len(params.NickName) == 0 { ctx.Fail(ecode.ParamsErr) return } var userId = fmt.Sprintf("u%v", snowflake.GenerateId()) var passWord = encrypt.BcryptHash(params.Password) var userType constvar.UserType var parentId string var parentName string if userInfo.UserType == constvar.UserTypeSuper { userType = constvar.UserTypePrimary // 主账户的父用户ID是自己 parentId = userId parentName = params.Username } else if userInfo.UserType == constvar.UserTypePrimary { userType = constvar.UserTypeSub parentId = userInfo.UserId parentName = userInfo.ParentId } else { ctx.Fail(ecode.NoPowerErr) return } user := &model.User{ID: userId, Username: params.Username, UserType: userType, NickName: params.NickName, Password: passWord, HeaderImg: params.HeaderImg, Enable: true, ParentId: parentId, ParentName: parentName, Phone: params.Phone, Email: params.Email} userReturn, errCode := userService.Register(user) if errCode != ecode.OK { ctx.Fail(errCode) return } if user.UserType == constvar.UserTypePrimary { // 主账户创建对应的数据库用户和排程数据库 err := model.NewMysql().CreateDatabase(user.Username) if err != nil { ctx.Fail(ecode.CreateDatabaseErr) return } defaultPwd := fmt.Sprintf("%v@Basic2023", user.Username) err = model.NewMysql().CreateUser(user.Username, defaultPwd, user.Username) if err != nil { ctx.Fail(ecode.CreateDatabaseUserErr) return } } ctx.OkWithDetailed(response.UserResponse{User: *userReturn}) } // ChangePassword // @Tags User // @Summary 用户修改密码 // @Produce application/json // @Param object body request.ChangePasswordReq true "查询参数" // @Success 200 {object} contextx.Response{} "成功" // @Router /api/user/changePassword [post] func (slf *BaseApi) ChangePassword(c *gin.Context) { var params request.ChangePasswordReq ctx, ok := contextx.NewContext(c, ¶ms) if !ok { return } u := &model.User{ID: utils.GetUserID(c), Password: params.Password} _, errCode := userService.ChangePassword(u, params.NewPassword) if errCode != ecode.OK { ctx.Fail(errCode) return } ctx.Ok() } // GetUserList // @Tags User // @Summary 分页获取用户列表(不传分页参数,获取全部) // @Produce application/json // @Param object body request.GetUserList true "查询参数" // @Success 200 {object} contextx.Response{data=response.PageResult} "成功" // @Router /api/user/getUserList [post] func (slf *BaseApi) GetUserList(c *gin.Context) { var params request.GetUserList ctx, ok := contextx.NewContext(c, ¶ms) if !ok { return } userInfo := utils.GetUserInfo(c) if len(userInfo.UserId) <= 0 || len(userInfo.ParentId) == 0 { ctx.Fail(ecode.UnknownErr) return } ctx.OkWithDetailed(response.PageResult{ Page: params.Page, PageSize: params.PageSize, }) } // DeleteUser // @Tags User // @Summary 删除用户 // @Produce application/json // @Param object body request.DeleteUserReq true "查询参数" // @Success 200 {object} contextx.Response{} "成功" // @Router /api/user/deleteUser [delete] func (slf *BaseApi) DeleteUser(c *gin.Context) { var params request.DeleteUserReq ctx, ok := contextx.NewContext(c, ¶ms) if !ok { return } if len(params.UserId) <= 0 { ctx.Fail(ecode.ParamsErr) return } userInfo := utils.GetUserInfo(c) if userInfo.UserType != constvar.UserTypePrimary || userInfo.UserId == params.UserId { ctx.Fail(ecode.NoPowerErr) return } err := userService.DeleteUser(params.UserId) if err != nil { logx.Errorf("删除失败! err:%v", err) ctx.Fail(ecode.DBErr) return } ctx.Ok() } // SetUserInfo // @Tags User // @Summary 设置用户信息 // @Produce application/json // @Param object body request.ChangeUserInfo true "查询参数" // @Success 200 {object} contextx.Response{} "成功" // @Router /api/user/setUserInfo [post] func (slf *BaseApi) SetUserInfo(c *gin.Context) { var params request.ChangeUserInfo ctx, ok := contextx.NewContext(c, ¶ms) if !ok { return } err := userService.SetUserInfo(model.User{ ID: params.ID, NickName: params.NickName, HeaderImg: params.HeaderImg, Phone: params.Phone, Email: params.Email, Pos: params.Pos, }) if err != nil { logx.Errorf("设置失败! err:%v", err) ctx.Fail(ecode.DBErr) return } ctx.Ok() } // SetSelfInfo // @Tags User // @Summary 设置用户信息 // @Produce application/json // @Param object body request.ChangeUserInfo true "查询参数" // @Success 200 {object} contextx.Response{} "成功" // @Router /api/user/setSelfInfo [post] func (slf *BaseApi) SetSelfInfo(c *gin.Context) { var params request.ChangeUserInfo ctx, ok := contextx.NewContext(c, ¶ms) if !ok { return } params.ID = utils.GetUserID(c) err := userService.SetUserInfo(model.User{ ID: params.ID, NickName: params.NickName, HeaderImg: params.HeaderImg, Phone: params.Phone, Email: params.Email, Pos: params.Pos, }) if err != nil { logx.Errorf("设置失败! err:%v", err) ctx.Fail(ecode.DBErr) return } ctx.Ok() } // GetUserInfo // @Tags User // @Summary 获取自身信息 // @Produce application/json // @Success 200 {object} contextx.Response{} "成功" // @Router /api/user/getUserInfo [post] func (slf *BaseApi) GetUserInfo(c *gin.Context) { ctx, ok := contextx.NewContext(c, nil) if !ok { return } id := utils.GetUserID(c) ReqUser, err := userService.GetUserInfo(id) if err != nil { logx.Errorf("获取失败! err:%v", err) ctx.Fail(ecode.DBErr) return } ctx.OkWithDetailed(response.UserResponse{ User: *ReqUser, }) } // ResetPassword // @Tags User // @Summary 重置用户密码 // @Produce application/json // @Param object body model.User true "查询参数" // @Success 200 {object} contextx.Response{} "成功" // @Router /api/user/resetPassword [post] func (slf *BaseApi) ResetPassword(c *gin.Context) { var params model.User ctx, ok := contextx.NewContext(c, ¶ms) if !ok { return } err := userService.ResetPassword(params.ID) if err != nil { logx.Errorf("重置失败! err:%v", err) ctx.Fail(ecode.DBErr) return } ctx.Ok() }