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()
|
}
|