237 lines
7.1 KiB
Go
237 lines
7.1 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"strings"
|
|
"time"
|
|
|
|
"go-common/app/job/main/passport-auth/model"
|
|
"go-common/library/log"
|
|
"go-common/library/queue/databus"
|
|
xtime "go-common/library/time"
|
|
)
|
|
|
|
var (
|
|
local, _ = time.LoadLocation("Local")
|
|
)
|
|
|
|
type tokenBMsg struct {
|
|
Action string
|
|
Table string
|
|
New *model.OldToken
|
|
}
|
|
|
|
type cookieBMsg struct {
|
|
Action string
|
|
Table string
|
|
New *model.OldCookie
|
|
}
|
|
|
|
func (s *Service) consumeproc() {
|
|
// fill callbacks
|
|
s.g.New = func(msg *databus.Message) (res interface{}, err error) {
|
|
bmsg := new(model.BMsg)
|
|
if err = json.Unmarshal(msg.Value, &bmsg); err != nil {
|
|
log.Error("json.Unmarshal(%s) error(%v)", msg.Value, err)
|
|
return
|
|
}
|
|
log.Info("receive aso msg action(%s) table(%s) key(%s) partition(%d) offset(%d) timestamp(%d) New(%s) Old(%s)",
|
|
bmsg.Action, bmsg.Table, msg.Key, msg.Partition, msg.Offset, msg.Timestamp, string(bmsg.New), string(bmsg.Old))
|
|
if strings.HasPrefix(bmsg.Table, "aso_app_perm") {
|
|
tokenBMsg := &tokenBMsg{
|
|
Action: bmsg.Action,
|
|
Table: bmsg.Table,
|
|
}
|
|
newToken := new(model.OldToken)
|
|
if err = json.Unmarshal(bmsg.New, &newToken); err != nil {
|
|
log.Error("json.Unmarshal(%s) error(%v)", bmsg.New, err)
|
|
return
|
|
}
|
|
tokenBMsg.New = newToken
|
|
return tokenBMsg, nil
|
|
} else if strings.HasPrefix(bmsg.Table, "aso_cookie_token") {
|
|
cookieBMsg := &cookieBMsg{
|
|
Action: bmsg.Action,
|
|
Table: bmsg.Table,
|
|
}
|
|
newCookie := new(model.OldCookie)
|
|
if err = json.Unmarshal(bmsg.New, newCookie); err != nil {
|
|
log.Error("json.Unmarshal(%s) error(%v)", bmsg.New, err)
|
|
return
|
|
}
|
|
cookieBMsg.New = newCookie
|
|
return cookieBMsg, nil
|
|
}
|
|
return
|
|
}
|
|
s.g.Split = func(msg *databus.Message, data interface{}) int {
|
|
if t, ok := data.(*tokenBMsg); ok {
|
|
return int(t.New.Mid)
|
|
} else if t, ok := data.(*cookieBMsg); ok {
|
|
return int(t.New.Mid)
|
|
}
|
|
return 0
|
|
}
|
|
s.g.Do = func(msgs []interface{}) {
|
|
for _, m := range msgs {
|
|
if msg, ok := m.(*tokenBMsg); ok {
|
|
for {
|
|
if err := s.handleToken(msg); err != nil {
|
|
log.Error("do handleToken error", err)
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
} else if msg, ok := m.(*cookieBMsg); ok {
|
|
for {
|
|
if err := s.handleCookie(msg); err != nil {
|
|
log.Error("do handleCookie error", err)
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// start the group
|
|
s.g.Start()
|
|
}
|
|
|
|
func (s *Service) handleCookie(cookie *cookieBMsg) (err error) {
|
|
newCookie := &model.Cookie{
|
|
Mid: cookie.New.Mid,
|
|
Session: cookie.New.Session,
|
|
CSRF: cookie.New.CSRFToken,
|
|
Expires: cookie.New.Expires,
|
|
}
|
|
csrfByte, _ := hex.DecodeString(cookie.New.CSRFToken)
|
|
if strings.ToLower(cookie.Action) == "insert" {
|
|
if _, err = s.dao.AddCookie(context.Background(), newCookie, []byte(newCookie.Session), csrfByte, time.Now()); err != nil {
|
|
return
|
|
}
|
|
return
|
|
} else if strings.ToLower(cookie.Action) == "delete" {
|
|
now := time.Now()
|
|
if _, err = s.dao.DelCookie(context.Background(), []byte(cookie.New.Session), now); err != nil {
|
|
log.Error("del db cookie(%s) error(%+v)", cookie.New.Session, err)
|
|
return
|
|
}
|
|
if _, err = s.dao.DelCookie(context.Background(), []byte(cookie.New.Session), previousMonth(now, -1)); err != nil {
|
|
log.Error("del db cookie(%s) error(%+v)", cookie.New.Session, err)
|
|
return
|
|
}
|
|
if newCookie.Expires > now.Unix() {
|
|
var t time.Time
|
|
if cookie.New.ModifyTime == "0000-00-00 00:00:00" {
|
|
t = time.Now()
|
|
} else {
|
|
t, err = time.ParseInLocation("2006-01-02 15:04:05", cookie.New.ModifyTime, local)
|
|
if err != nil {
|
|
log.Error("handleCookie error: ctime parse error(%+v) cookie(%+v)", err, cookie.New)
|
|
return
|
|
}
|
|
}
|
|
timestamp := xtime.Time(t.Unix())
|
|
newCookie.Ctime = timestamp
|
|
if _, err = s.dao.AddCookieDeleted(context.Background(), newCookie, []byte(newCookie.Session), csrfByte, t); err != nil {
|
|
return
|
|
}
|
|
}
|
|
if err = s.authRPC.DelCookieCookie(context.Background(), cookie.New.Session); err != nil {
|
|
log.Error("del cache cookie(%s) error(%+v)", cookie.New.Session, err)
|
|
}
|
|
if err = s.dao.AsoCleanCache(context.Background(), "", cookie.New.Session, cookie.New.Mid); err != nil {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) handleToken(token *tokenBMsg) (err error) {
|
|
var t time.Time
|
|
t, err = time.ParseInLocation("2006-01-02 15:04:05", token.New.CTime, local)
|
|
if err != nil {
|
|
log.Error("handleToken error: ctime parse err. (%+v)", token.New)
|
|
return
|
|
}
|
|
timestamp := xtime.Time(t.Unix())
|
|
newToken := &model.Token{
|
|
Mid: token.New.Mid,
|
|
Token: token.New.AccessToken,
|
|
AppID: token.New.AppID,
|
|
Expires: token.New.Expires,
|
|
Type: token.New.Type,
|
|
Ctime: timestamp,
|
|
}
|
|
tokenByte, _ := hex.DecodeString(newToken.Token)
|
|
if strings.ToLower(token.Action) == "insert" {
|
|
if _, err = s.dao.AddToken(context.Background(), newToken, tokenByte, t); err != nil {
|
|
return
|
|
}
|
|
if token.New.RefreshToken == "" {
|
|
return
|
|
}
|
|
newRefresh := &model.Refresh{
|
|
Mid: token.New.Mid,
|
|
Refresh: token.New.RefreshToken,
|
|
Token: token.New.AccessToken,
|
|
AppID: token.New.AppID,
|
|
Expires: token.New.Expires, // 需要考虑+30天
|
|
}
|
|
tokenByteRefresh, _ := hex.DecodeString(newRefresh.Token)
|
|
refreshByte, _ := hex.DecodeString(newRefresh.Refresh)
|
|
if _, err = s.dao.AddRefresh(context.Background(), newRefresh, refreshByte, tokenByteRefresh, t); err != nil {
|
|
return
|
|
}
|
|
} else if strings.ToLower(token.Action) == "delete" {
|
|
now := time.Now()
|
|
if _, err = s.dao.DelToken(context.Background(), tokenByte, now); err != nil {
|
|
log.Error("del db token(%s) error(%+v)", token.New.AccessToken, err)
|
|
return
|
|
}
|
|
if _, err = s.dao.DelToken(context.Background(), tokenByte, previousMonth(now, -1)); err != nil {
|
|
log.Error("del db token(%s) error(%+v)", token.New.AccessToken, err)
|
|
return
|
|
}
|
|
if _, err = s.dao.DelToken(context.Background(), tokenByte, previousMonth(now, -2)); err != nil {
|
|
log.Error("del db token(%s) error(%+v)", token.New.AccessToken, err)
|
|
return
|
|
}
|
|
if _, err = s.dao.AddTokenDeleted(context.Background(), newToken, tokenByte, t); err != nil {
|
|
return
|
|
}
|
|
if err = s.authRPC.DelTokenCache(context.Background(), token.New.AccessToken); err != nil {
|
|
log.Error("del cache token(%s) error(%+v)", token.New.AccessToken, err)
|
|
}
|
|
if err = s.dao.AsoCleanCache(context.Background(), token.New.AccessToken, "", token.New.Mid); err != nil {
|
|
return
|
|
}
|
|
if token.New.RefreshToken == "" {
|
|
return
|
|
}
|
|
refreshByte, _ := hex.DecodeString(token.New.RefreshToken)
|
|
if _, err = s.dao.DelRefresh(context.Background(), refreshByte, t); err != nil {
|
|
log.Error("del db refresh(%s) error(%+v)", token.New.RefreshToken, err)
|
|
return
|
|
}
|
|
if _, err = s.dao.DelRefresh(context.Background(), refreshByte, previousMonth(t, -2)); err != nil {
|
|
log.Error("del db refresh(%s) error(%+v)", token.New.RefreshToken, err)
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func previousMonth(t time.Time, delta int) time.Time {
|
|
if delta == 0 {
|
|
return t
|
|
}
|
|
year, month, _ := t.Date()
|
|
thisMonthFirstDay := time.Date(year, month, 1, 1, 1, 1, 1, t.Location())
|
|
return thisMonthFirstDay.AddDate(0, delta, 0)
|
|
}
|