go-common/app/admin/main/aegis/service/token_bind.go
2019-04-22 18:49:16 +08:00

432 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"context"
"fmt"
"sort"
"strconv"
"strings"
"time"
"github.com/jinzhu/gorm"
"go-common/app/admin/main/aegis/model"
"go-common/app/admin/main/aegis/model/net"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/xstr"
)
func (s *Service) checkBindToken(c context.Context, tokenID []int64) (tokenMap map[string]*net.Token, err error, msg string) {
var (
tokens []*net.Token
)
tokenMap = map[string]*net.Token{}
if len(tokenID) == 0 {
return
}
if tokens, err = s.gorm.Tokens(c, tokenID); err != nil {
log.Error("checkBindToken s.gorm.Tokens error(%v)", err)
return
}
for _, tk := range tokens {
if !tk.IsAssign() {
err = ecode.AegisTokenNotAssign
msg = fmt.Sprintf(ecode.AegisTokenNotAssign.Message(), tk.ChName)
return
}
id := strconv.FormatInt(tk.ID, 10)
tokenMap[id] = tk
}
if len(tokenID) == len(tokens) {
return
}
for _, id := range tokenID {
if _, exist := tokenMap[strconv.FormatInt(id, 10)]; !exist {
err = ecode.AegisTokenNotFound
msg = fmt.Sprintf("id=%d的令牌 %s", id, ecode.AegisTokenNotAssign.Message())
return
}
}
return
}
func (s *Service) fetchOldBindAndLog(c context.Context, elementID int64, tp []int8) (all map[int64]*net.TokenBind, availableLog []string, err error) {
var (
oldBindMap map[int64][]*net.TokenBind
oldBindToken map[int64][]*net.Token
)
all = map[int64]*net.TokenBind{}
availableLog = []string{}
if oldBindMap, err = s.gorm.TokenBindByElement(c, []int64{elementID}, tp, false); err != nil {
log.Error("fetchOldBindAndLog s.gorm.TokenBindByElement error(%v)", err)
return
}
oldBindAvailable := []*net.TokenBind{}
allBindMap := map[int64]*net.TokenBind{}
for _, item := range oldBindMap[elementID] {
allBindMap[item.ID] = item
oldBindAvailable = append(oldBindAvailable, item)
}
if oldBindToken, err = s.bindTokens(c, oldBindAvailable); err != nil {
log.Error("fetchOldBindAndLog s.bindTokens error(%v)", err)
return
}
for bindID, items := range oldBindToken {
sub := []string{}
for _, item := range items {
sub = append(sub, item.FormatLog())
}
chname := ""
tp := int8(0)
if allBindMap[bindID] != nil {
chname = allBindMap[bindID].ChName
tp = allBindMap[bindID].Type
}
availableLog = append(availableLog, fmt.Sprintf(net.BindLogTemp, chname, tp, strings.Join(sub, ",")))
}
all = allBindMap
return
}
func (s *Service) compareFlowBind(c context.Context, tx *gorm.DB, flowID int64, tokenID []int64, isUpdate bool) (diff string, changed []int64, err error, msg string) {
var (
tokenMap map[string]*net.Token
oldBindAll = map[int64]*net.TokenBind{}
newFormatLog = []string{}
oldFormatLog = []string{}
disable = time.Now()
recovered = net.Recovered
existTokenID = map[string]int{}
)
log.Info("compareFlowBind start flow(%d) tokenid(%+v) isUpdate(%v)", flowID, tokenID, isUpdate)
//新绑定查询检查是否为赋值语句token & token是否存在
if len(tokenID) > 0 {
if tokenMap, err, msg = s.checkBindToken(c, tokenID); err != nil {
log.Error("compareFlowBind s.checkBindToken error(%v)", err)
return
}
for _, item := range tokenMap {
newFormatLog = append(newFormatLog, fmt.Sprintf(net.BindLogTemp, item.ChName, item.Type, item.FormatLog()))
}
}
//获取现有所有绑定和可用绑定
if isUpdate {
if oldBindAll, oldFormatLog, err = s.fetchOldBindAndLog(c, flowID, []int8{net.BindTypeFlow}); err != nil {
log.Error("compareFlowBind s.fetchOldBindAndLog error(%v)", err)
return
}
}
if len(tokenMap) == 0 && len(oldBindAll) == 0 {
return
}
//从旧的中过滤新的
for _, item := range oldBindAll {
if _, exist := tokenMap[item.TokenID]; exist {
existTokenID[item.TokenID] = 1
if item.IsAvailable() {
continue
}
item.DisableTime = recovered
} else {
item.DisableTime = disable
}
if err = s.gorm.UpdateFields(c, tx, net.TableTokenBind, item.ID, map[string]interface{}{"disable_time": item.DisableTime}); err != nil {
log.Error("compareFlowBind s.gorm.UpdateFields error(%v)", err)
return
}
changed = append(changed, item.ID)
}
//从新的中过滤旧的
for tokenID, tk := range tokenMap {
if _, exist := existTokenID[tokenID]; exist {
continue
}
nw := &net.TokenBind{TokenID: tokenID, ChName: tk.ChName, ElementID: flowID, Type: net.BindTypeFlow}
if err = s.gorm.AddItem(c, tx, nw); err != nil {
log.Error("compareFlowBind s.gorm.AddItem error(%v)", err)
return
}
changed = append(changed, nw.ID)
}
if len(changed) > 0 && (len(newFormatLog) > 0 || len(oldFormatLog) > 0) {
diff = model.LogFieldTemp(model.LogFieldTokenID, strings.Join(newFormatLog, ";"), strings.Join(oldFormatLog, ";"), isUpdate)
}
log.Info("compareFlowBind end flow(%d) tokenid(%+v) isupdate(%v) diff(%s)", flowID, tokenID, isUpdate, diff)
return
}
func (s *Service) compareTranBind(c context.Context, tx *gorm.DB, tranID int64, binds []*net.TokenBindParam, isUpdate bool) (diff string, changed []int64, err error, msg string) {
var (
relatedTokenID []int64
tokenID = []int64{}
existBindParam = map[int64]*net.TokenBindParam{}
tokenMap map[string]*net.Token
oldBindAll = map[int64]*net.TokenBind{}
newFormatLog = []string{}
oldFormatLog []string
disable = time.Now()
recovered = net.Recovered
)
log.Info("compareTranBind start transition(%d) binds(%+v) isUpdate(%v)", tranID, binds, isUpdate)
//现有全部绑定关系和可用绑定
if isUpdate {
if oldBindAll, oldFormatLog, err = s.fetchOldBindAndLog(c, tranID, net.BindTranType); err != nil {
log.Error("compareTranBind s.fetchOldBindAndLog error(%v)", err)
return
}
}
//新绑定处理
for _, item := range binds {
//是否已存在
if item.ID > 0 && oldBindAll[item.ID] == nil {
log.Error("compareTranBind binds(%+v) not found", item)
err = ecode.RequestErr
return
}
if item.ID > 0 {
existBindParam[item.ID] = item
}
//tokenid排序重组
if relatedTokenID, err = xstr.SplitInts(item.TokenID); err != nil {
log.Error("compareTranBind xstr.SplitInts(%+v) error(%v)", item, err)
return
}
if len(relatedTokenID) == 0 {
log.Error("compareTranBind bind(%+v) tokenid empty ", item)
err = ecode.RequestErr
return
}
sort.Sort(net.Int64Slice(relatedTokenID))
item.TokenID = xstr.JoinInts(relatedTokenID)
tokenID = append(tokenID, relatedTokenID...)
}
//检查是否为赋值语句token & token是否存在
if len(tokenID) > 0 {
if tokenMap, err, msg = s.checkBindToken(c, tokenID); err != nil {
log.Error("compareTranBind s.checkBindToken error(%v)", err)
return
}
}
for _, item := range binds {
//前端没传中文名则自行组合
nwLog := []string{}
chname := item.ChName
tkname := map[string]int64{}
for _, tid := range strings.Split(item.TokenID, ",") {
tk := tokenMap[tid]
if tk == nil {
continue
}
//token_name级别的过滤
if tkname[tk.Name] > 0 {
log.Error("compareTranBind bind(%+v) duplicated with token name(%s)", item, tk.Name)
err = ecode.RequestErr
return
}
tkname[tk.Name] = tk.ID
if item.ChName == "" {
chname = chname + tokenMap[tid].ChName
}
nwLog = append(nwLog, tokenMap[tid].FormatLog())
}
chnameMerge := []rune(chname)
last := len(chnameMerge)
if last > 16 {
last = 16
}
item.ChName = string(chnameMerge[:last])
newFormatLog = append(newFormatLog, fmt.Sprintf(net.BindLogTemp, item.ChName, item.Type, strings.Join(nwLog, ",")))
}
//从旧的中过滤新的
for id, item := range oldBindAll {
updateField := map[string]interface{}{}
if newParam, exist := existBindParam[id]; exist {
if !item.IsAvailable() {
item.DisableTime = recovered
updateField["disable_time"] = recovered
}
if item.TokenID != newParam.TokenID {
item.TokenID = newParam.TokenID
updateField["token_id"] = newParam.TokenID
}
if newParam.ChName != "" && newParam.ChName != item.ChName {
item.ChName = newParam.ChName
updateField["ch_name"] = newParam.ChName
}
if newParam.Type != item.Type {
item.Type = newParam.Type
updateField["type"] = newParam.Type
}
} else if item.IsAvailable() {
item.DisableTime = disable
updateField["disable_time"] = disable
} else {
continue
}
if len(updateField) == 0 {
continue
}
if err = s.gorm.UpdateFields(c, tx, net.TableTokenBind, item.ID, updateField); err != nil {
log.Error("compareTranBind s.gorm.UpdateFields error(%v)", err)
return
}
changed = append(changed, item.ID)
}
//从新的中过滤旧的
for _, newParam := range binds {
if newParam.ID > 0 && oldBindAll[newParam.ID] != nil {
continue
}
nw := &net.TokenBind{TokenID: newParam.TokenID, ChName: newParam.ChName, ElementID: tranID, Type: newParam.Type}
if err = s.gorm.AddItem(c, tx, nw); err != nil {
log.Error("compareTranBind s.gorm.AddItem error(%v)", err)
return
}
changed = append(changed, nw.ID)
}
if len(changed) > 0 && (len(newFormatLog) > 0 || len(oldFormatLog) > 0) {
diff = model.LogFieldTemp(model.LogFieldTokenID, strings.Join(newFormatLog, ";"), strings.Join(oldFormatLog, ";"), isUpdate)
}
log.Info("compareTranBind end transition(%d) binds(%+v) isupdate(%v) diff(%s)", tranID, binds, isUpdate, diff)
return
}
func (s *Service) bindTokens(c context.Context, binds []*net.TokenBind) (result map[int64][]*net.Token, err error) {
var (
tokenIDSlice []int64
tokens []*net.Token
)
result = map[int64][]*net.Token{}
if len(binds) == 0 {
return
}
tids := []int64{}
bindTokenMap := map[int64][]int64{}
for _, item := range binds {
if tokenIDSlice, err = xstr.SplitInts(item.TokenID); err != nil {
log.Error("tokenBindDetail xstr.SplitInts(%s) error(%v)", item.TokenID, err)
return
}
bindTokenMap[item.ID] = tokenIDSlice
if len(tokenIDSlice) == 0 {
continue
}
tids = append(tids, tokenIDSlice...)
}
if len(tids) == 0 {
return
}
if tokens, err = s.gorm.Tokens(c, tids); err != nil {
log.Error("tokenBindDetail s.gorm.Tokens(%v) error(%v)", tids, err)
return
}
if len(tokens) == 0 {
return
}
tokenMap := map[int64]*net.Token{}
for _, item := range tokens {
tokenMap[item.ID] = item
}
for bindID, tidList := range bindTokenMap {
result[bindID] = []*net.Token{}
for _, id := range tidList {
if tokenMap[id] == nil {
continue
}
result[bindID] = append(result[bindID], tokenMap[id])
}
}
return
}
//tokenBindDetail 一条绑定的详细信息获取了token详情
func (s *Service) tokenBindDetail(c context.Context, binds []*net.TokenBind) (result []*net.TokenBindDetail, err error) {
var (
tokenIDSlice []int64
tokens []*net.Token
)
if len(binds) == 0 {
return
}
details := make([]*net.TokenBindDetail, len(binds))
//get tokens
tids := []int64{}
bindTokenMap := map[string][]int64{}
for k, item := range binds {
details[k] = &net.TokenBindDetail{
ID: item.ID,
Type: item.Type,
ElementID: item.ElementID,
TokenID: item.TokenID,
ChName: item.ChName,
DisableTime: item.DisableTime,
Tokens: []*net.Token{},
}
if tokenIDSlice, err = xstr.SplitInts(item.TokenID); err != nil {
log.Error("tokenBindDetail xstr.SplitInts(%s) error(%v)", item.TokenID, err)
return
} else if len(tokenIDSlice) == 0 {
continue
} else {
tids = append(tids, tokenIDSlice...)
}
bindTokenMap[item.TokenID] = tokenIDSlice
}
if len(tids) == 0 {
result = details
return
}
if tokens, err = s.gorm.Tokens(c, tids); err == nil && len(tokens) == 0 {
log.Error("tokenBindDetail s.gorm.Tokens(%v) not found", tids)
result = details
err = nil
return
}
if err != nil {
log.Error("TokenBindDetail find token error(%v) tids(%v)", err, tids)
return
}
tokenMap := make(map[int64]*net.Token, len(tokens))
for _, item := range tokens {
tokenMap[item.ID] = item
}
//dispatch tokens to detail
for _, item := range details {
for _, id := range bindTokenMap[item.TokenID] {
if tokenMap[id] != nil {
item.Tokens = append(item.Tokens, tokenMap[id])
}
}
}
result = details
return
}