Initial commit

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-11-07 10:47:18 +08:00
co-authored by Claude Opus 4.7
commit 79ac89b458
708 changed files with 151634 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
package srv_mwacc
import (
"context"
"time"
"videoweb/pub/common/crypt"
"videoweb/pub/common/errors"
"videoweb/pub/models/mwacc"
"go.mongodb.org/mongo-driver/bson"
)
// // 删除角色
// func AccDel(ctx context.Context, roleId int64) (ok bool, err error){
//
// }
// 更改
func AccUp(ctx context.Context, upDoc *AccUpDoc) (ok bool, err error) {
c, err := mwacc.AccCountByFilter(ctx, bson.M{
mwacc.FN.MwAcc.Acc: upDoc.Acc,
mwacc.FN.MwAcc.Id: bson.M{
"$ne": upDoc.Id,
},
})
if c > 0 {
err = errors.MakeWithMsg(errors.DBInsert, "账户名已存在")
return false, err
}
set := bson.M{}
set = bson.M{
mwacc.FN.MwAcc.UserName: upDoc.UserName,
mwacc.FN.MwAcc.Acc: upDoc.Acc,
mwacc.FN.MwAcc.Email: upDoc.Email,
mwacc.FN.MwAcc.RoleId: upDoc.RoleId,
mwacc.FN.MwAcc.IsEnb: upDoc.IsEnb,
mwacc.FN.MwAcc.UpdatedAt: time.Now(),
mwacc.FN.MwAcc.LimitIP: upDoc.LimitIP,
}
err = mwacc.UpOneAccByFilter(ctx, bson.M{
mwacc.FN.MwAcc.Id: upDoc.Id,
}, set)
if err != nil {
err = errors.MakeWithErr(errors.DBUpdate, err)
return false, err
}
return true, err
}
// 更改账号密码
func AccUpPwd(ctx context.Context, upDoc *AccUpPwdDoc) (ok bool, err error) {
set := bson.M{}
set = bson.M{
mwacc.FN.MwAcc.Pwd: crypt.StrToMd5(upDoc.Pwd),
mwacc.FN.MwAcc.UpdatedAt: time.Now(),
}
err = mwacc.UpOneAccByFilter(ctx, bson.M{
mwacc.FN.MwAcc.Id: upDoc.Id,
}, set)
if err != nil {
err = errors.MakeWithErr(errors.DBUpdate, err)
return false, err
}
mwacc.DeleteOneToken(ctx, bson.M{mwacc.FN.MwAccToken.AccId: upDoc.Id})
return true, err
}
+32
View File
@@ -0,0 +1,32 @@
package srv_mwacc
type AccUpDoc struct {
// 账号Id
Id int64 `json:"id,omitempty"`
// 用户名
UserName string `json:"user_name,omitempty"`
// 账号
Acc string `json:"acc,omitempty"`
// // 密码
// Pwd string `json:"pwd,omitempty"`
// 邮箱
Email string `json:"email,omitempty"`
// 角色Id
RoleId int64 `json:"role_id,omitempty"`
// 使能
IsEnb bool `json:"is_enb,omitempty"`
// 允许访问的IP
LimitIP []string `json:"limitIP,omitempty"`
}
type ProductAccountInfo struct {
Id int64 `json:"id"`
Name string `json:"name"`
}
type AccUpPwdDoc struct {
// 账号Id
Id int64 `json:"id,omitempty"`
// 密码
Pwd string `json:"pwd,omitempty"`
}
+179
View File
@@ -0,0 +1,179 @@
package srv_mwacc
import (
"context"
"strings"
"time"
"videoweb/pub/common/crypt"
"videoweb/pub/common/enum/consts"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/pub/common/utils"
"videoweb/pub/google"
"videoweb/pub/models/mwacc"
"videoweb/web/webg"
"github.com/skip2/go-qrcode"
"go.mongodb.org/mongo-driver/bson"
)
func generateToken(userID int64) (string, error) {
return utils.GenerateUserToken(utils.UserClaims{UserID: userID, Expire: consts.AdminJwtTokenExpire}, webg.Conf.JwtKey)
}
// AccSLogin 账号登录
func AccSLogin(ctx context.Context, acc string, pwd string) (*mwacc.MwAcc, *srvdef.SrvErr) {
var data *mwacc.MwAcc
res, dataErr := mwacc.FindOneAccByFilter(ctx, bson.M{
mwacc.FN.MwAcc.Acc: acc,
})
if dataErr != nil || res.Id == 0 {
return data, srvdef.New(srvdef.AccountIsNotExists, srvdef.AccountIsNotExists.Msg(), "")
}
if !res.IsEnb {
return data, srvdef.New(srvdef.AccountErrAccessForbid, srvdef.AccountErrAccessForbid.Msg(), "")
}
// 通过验证,再次验证密码是否正确
md5pwd := crypt.StrToMd5(pwd)
if res.Pwd != md5pwd {
return data, srvdef.New(srvdef.AccountErrPasswordError, srvdef.AccountErrPasswordError.Msg(), "")
}
// slogin 仅允许角色名含“客服”的账号登录
if !isCustomerServiceRole(ctx, res) {
return data, srvdef.New(srvdef.ErrUserPermission, "仅客服角色可登录", "")
}
getToken, err := generateToken(res.Id)
if err != nil {
return data, srvdef.New(srvdef.GenerateTokenFailed, srvdef.GenerateTokenFailed.Msg(), "")
}
_ = mwacc.UpOneAccByFilter(ctx, bson.M{
mwacc.FN.MwAcc.Id: res.Id,
}, bson.M{
mwacc.FN.MwAcc.LastTime: time.Now(),
})
// 更新最近登录时间
data = res
data.Token = getToken
return data, nil
}
// isCustomerServiceRole 判断账号角色名是否包含“客服”
func isCustomerServiceRole(ctx context.Context, acc *mwacc.MwAcc) bool {
if acc == nil {
return false
}
roleName := acc.RoleName
if roleName == "" && acc.RoleId > 0 {
role, serr := mwacc.FindOneRoleByFilter(ctx, bson.M{mwacc.FN.MwRole.Id: acc.RoleId})
if serr == nil && role != nil {
roleName = role.Name
}
}
return strings.Contains(roleName, "客服")
}
// 账号登录
func AccLogin(ctx context.Context, acc string, pwd string, code string) (*mwacc.MwAcc, *srvdef.SrvErr) {
var data *mwacc.MwAcc
res, dataErr := mwacc.FindOneAccByFilter(ctx, bson.M{
mwacc.FN.MwAcc.Acc: acc,
})
if dataErr != nil || res.Id == 0 {
return data, srvdef.New(srvdef.AccountIsNotExists, srvdef.AccountIsNotExists.Msg(), "")
}
if !res.IsEnb {
return data, srvdef.New(srvdef.AccountErrAccessForbid, srvdef.AccountErrAccessForbid.Msg(), "")
}
// 通过验证,再次验证密码是否正确
md5pwd := crypt.StrToMd5(pwd)
if res.Pwd != md5pwd {
return data, srvdef.New(srvdef.AccountErrPasswordError, srvdef.AccountErrPasswordError.Msg(), "")
}
if !res.IsBase32 {
// 谷歌绑定二维码
googleUrl := google.NewGoogleAuth().GetQrcode(acc, res.Base32)
qrCodePNG, _ := qrcode.Encode(googleUrl, qrcode.Medium, 256)
bq := &mwacc.MwAcc{}
bq.Qurl = qrCodePNG
data = bq
} else {
// hf屏蔽
if webg.Conf.RunMod == "prod" && (res.RoleId != 46761 && res.RoleId != 29601) {
if code == "" {
return data, srvdef.New(srvdef.ErrCaptcha, srvdef.ErrCaptcha.Msg(), "")
}
result, Verr := google.NewGoogleAuth().VerifyCode(res.Base32, code)
if Verr != nil || !result {
return data, srvdef.New(srvdef.ErrCaptchaInvalid, srvdef.ErrCaptchaInvalid.Msg(), "")
}
}
// 通过验证,再次验证密码是否正确
pwd := crypt.StrToMd5(pwd)
if res.Pwd != pwd {
return data, srvdef.New(srvdef.AccountErrPasswordError, srvdef.AccountErrPasswordError.Msg(), "")
}
getToken, err := generateToken(res.Id)
if err != nil {
return data, srvdef.New(srvdef.GenerateTokenFailed, srvdef.GenerateTokenFailed.Msg(), "")
}
_ = mwacc.UpOneAccByFilter(ctx, bson.M{
mwacc.FN.MwAcc.Id: res.Id,
}, bson.M{
mwacc.FN.MwAcc.LastTime: time.Now(),
})
// 更新最近登录时间
data = res
data.Token = getToken
}
return data, nil
}
// 账号登录
func ProductAccountList(ctx context.Context, accId int64) ([]ProductAccountInfo, *srvdef.SrvErr) {
resp := make([]ProductAccountInfo, 0)
accInfo, serr := mwacc.FindOneAccByFilter(ctx, bson.M{
mwacc.FN.MwAcc.Id: accId,
})
if serr != nil {
log.Error("ProductAccountList FindOneAccByFilter", log.Any("serr", serr))
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
if accInfo.RoleId == 1000 {
resp = append(resp, ProductAccountInfo{
Id: accInfo.Id,
Name: accInfo.UserName,
})
return resp, nil
}
accList, lerr := mwacc.FindManyAccByFilter(ctx, bson.M{
mwacc.FN.MwAcc.RoleId: 1000,
})
if lerr != nil {
log.Error("ProductAccountList FindManyAccByFilter", log.Any("serr", serr))
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
for _, v := range accList {
resp = append(resp, ProductAccountInfo{
Id: v.Id,
Name: v.UserName,
})
}
return resp, nil
}
+221
View File
@@ -0,0 +1,221 @@
package srv_mwacc
import (
"context"
"fmt"
"time"
"videoweb/pub/common/errors"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/mwacc"
"go.mongodb.org/mongo-driver/bson"
)
// 删除角色
func RoleDel(ctx context.Context, roleId int64) (bool, *srvdef.SrvErr) {
res, err := mwacc.FindOneRoleByFilter(ctx, bson.M{mwacc.FN.MwRole.Id: roleId})
if err != nil || res.Id == 0 {
log.ZapLog.Error(fmt.Sprintf("search error %v", err))
return false, err
}
// 查询记录是否有账户
roles, err1 := mwacc.RoleAggregate(ctx,
[]bson.M{
{"$match": bson.M{mwacc.FN.MwRole.Id: roleId}},
{"$limit": 1},
{"$lookup": bson.M{
"localField": mwacc.FN.MwRole.Id,
"from": mwacc.TN.MwAcc,
"foreignField": mwacc.FN.MwAcc.RoleId,
"as": "onlyRole",
}},
{"$unwind": "$onlyRole"},
{"$project": bson.M{
mwacc.FN.MwRole.Id: 1,
"onlyRole.roleId": 1,
}},
})
if err1 != nil {
log.Error("角色删除失败", log.Any("roleId", roleId))
return false, srvdef.New(srvdef.ErrDbDeleteError, "", "")
}
if len(roles) > 0 {
log.Error("角色删除失败", log.Any("roleId", roleId))
return false, srvdef.New(srvdef.ErrDbDeleteError, "删除失败,此角色有帐户", "")
}
serr := mwacc.DelRoleByFilter(ctx, bson.M{mwacc.FN.MwRole.Id: roleId})
if serr != nil {
return false, serr
}
return true, nil
}
// 获取信息
func RoleGetInfo(ctx context.Context, roleId int64) (*mwacc.MwRole, error) {
rest, err := mwacc.FindOneRoleByFilter(ctx, bson.M{
mwacc.FN.MwRole.Id: roleId,
})
if err != nil {
return nil, err
}
return rest, nil
}
// 角色id
// 角色更新
func RoleUp(ctx context.Context, id int64, name string, desc string, isEnb bool) (ok bool, err error) {
roleCount, err := mwacc.RoleCountByFilter(ctx, bson.M{
mwacc.FN.MwRole.Name: name,
mwacc.FN.MwRole.Id: bson.M{
"$ne": id,
},
})
if roleCount > 0 {
err = errors.MakeWithMsg(errors.DBInsert, "角色名称已存在")
return false, err
}
err = mwacc.UpOneRoleByFilter(ctx, bson.M{
mwacc.FN.MwRole.Id: id,
}, bson.M{
"$set": bson.M{
mwacc.FN.MwRole.Name: name,
mwacc.FN.MwRole.Desc: desc,
mwacc.FN.MwRole.IsEnb: isEnb,
mwacc.FN.MwRole.UpdatedAt: time.Now(),
},
})
if err != nil {
log.ZapLog.Error(fmt.Sprintf("RoleUp error %v", err))
err = errors.MakeWithErr(errors.DBUpdate, err)
return
}
return true, nil
}
// 设置角色状态
func RoleEnable(ctx context.Context, roleId int64, IsEnb bool) (bool, *srvdef.SrvErr) {
rest, err := mwacc.FindOneRoleByFilter(ctx, bson.M{
mwacc.FN.MwRole.Id: roleId,
})
if err != nil || rest.Id == 0 {
return false, err
}
// count, err := mwacc.RoleAggregate(ctx, []bson.M{
// {"$match": bson.M{
// mwacc.FN.MwRole.Id: roleId,
// }},
// {"$limit": 1},
// {"$lookup": bson.M{
// "localField": mwacc.FN.MwRole.Id,
// "from": mwacc.TN.MwAcc,
// "foreignField": mwacc.FN.MwAcc.RoleId,
// "as": "onlyRole",
// }},
// {"$unwind": "$onlyRole"},
// {"$project": bson.M{
// "roleId": 1,
// "onlyRole.roleId": 1,
// }},
// })
data, err1 := mwacc.FindManyAccByFilter(ctx, bson.M{mwacc.FN.MwAcc.RoleId: roleId})
if err1 != nil {
return false, err1
}
if len(data) > 0 && IsEnb == false {
return false, srvdef.New(srvdef.ErrDbUpdateError, "更新失败,此角色下拥有管理员", "")
}
StatusErr := mwacc.UpOneRoleByFilter(ctx, bson.M{
mwacc.FN.MwRole.Id: roleId,
}, bson.M{
"$set": bson.M{
mwacc.FN.MwRole.IsEnb: IsEnb,
},
})
if StatusErr != nil {
return false, StatusErr
}
return true, nil
}
// ////////////////////////////////////////////////////////////////////////////
// 数据库Router转网站Router
// // 角色权限列表
// func RoleAuthList(ctx context.Context, roleId int64) (*mwacc.MwRole, error) {
// opt := &options.FindOneOptions{}
// opt.SetProjection(bson.M{
// mwacc.FN.MwRole.Id: 1,
// mwacc.FN.MwRole.Router: 1,
// })
// res, err := mwacc.FindOneRoleByFilter(ctx, bson.M{mwacc.FN.MwRole.Id: roleId})
// if err != nil {
// return &mwacc.MwRole{}, err
// }
// if res.Id != 0 {
// return res, nil
// }
// return nil, nil
// }
func handleMenu(ctx context.Context, reqRouter []*mwacc.Router, apiMap map[string]int64) map[string]int64 {
if apiMap == nil {
apiMap = make(map[string]int64)
}
for _, v := range reqRouter {
if v.Children != nil && len(v.Children) != 0 {
childs := make([]*mwacc.Router, 0)
for _, v := range v.Children {
childs = append(childs, &v)
}
apiMap = handleMenu(ctx, childs, apiMap)
}
if v.ApiUrl != nil && len(v.ApiUrl) != 0 {
for _, v := range v.ApiUrl {
if v.Status == true {
for _, value := range v.Url {
apiMap[value] = 1
}
}
}
}
}
return apiMap
}
// 更新权限
func UpAuth(ctx context.Context, id int64, dataRouter []*mwacc.Router) (ok bool, err error) {
apiMap := handleMenu(ctx, dataRouter, nil)
keys := make([]string, 0)
for k := range apiMap {
keys = append(keys, k)
}
return mwacc.UpRoleAuth(ctx, id, keys, dataRouter)
}