Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"aes.go",
"data_fix.go",
"duplicate.go",
"dynamic_compare.go",
"full_compare.go",
"service.go",
"utils.go",
],
importpath = "go-common/app/job/main/passport-user-compare/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/passport-user-compare/conf:go_default_library",
"//app/job/main/passport-user-compare/dao:go_default_library",
"//app/job/main/passport-user-compare/model:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/go-sql-driver/mysql:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/robfig/cron:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["aes_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/passport-user-compare/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,49 @@
package service
import (
"bytes"
"crypto/aes"
"crypto/cipher"
)
// Encrypt aes encrypt
func Encrypt(origData []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
origData = PKCS5Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}
// Decrypt aes encrypt
func Decrypt(crypted []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
origData := make([]byte, len(crypted))
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
return origData, nil
}
// PKCS5Padding padding
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
// PKCS5UnPadding unpadding
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}

View File

@@ -0,0 +1,60 @@
package service
import (
"fmt"
"strconv"
"strings"
"testing"
"encoding/hex"
"go-common/app/job/main/passport-user-compare/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_Encrypt(t *testing.T) {
Convey("Encrypt param ", t, func() {
input := []byte("15253340367")
res, err := Encrypt(input, []byte("bili_@F1C2^Y_enc"))
ShouldBeNil(err)
ShouldNotBeNil(res)
fmt.Printf("res is (%+v)\n", res)
fmt.Printf("hex is (%+v) \n", strings.ToUpper(hex.EncodeToString(res)))
})
}
func TestService_Decrypt(t *testing.T) {
Convey("Decrypt param ", t, func() {
var (
in []byte
err error
res []byte
)
sns := &model.OriginAccountSns{
SinaUID: 5208921734,
}
th := &model.UserThirdBind{
OpenID: "5208921734",
}
if s, err1 := strconv.ParseInt(th.OpenID, 10, 64); err1 != nil {
fmt.Printf("error happen %+v", err1)
} else {
fmt.Println(s == sns.SinaUID)
}
a := new(model.UserBase)
fmt.Printf("(%+v)", a == nil)
if in, err = hex.DecodeString("3DEF2C03D0C822C57C5E3A931C087F27"); err != nil {
fmt.Printf("err , (%+v)\n", err)
} else {
fmt.Printf("in, (%+v)\n", in)
}
res, err = Decrypt(in, []byte("bili_@F1C2^Y_enc"))
ShouldBeNil(err)
ShouldNotBeNil(res)
fmt.Printf("(%+v) ,len is %d\n", string(res), len(in))
})
}

View File

@@ -0,0 +1,618 @@
package service
import (
"context"
"encoding/hex"
"strings"
"time"
"go-common/app/job/main/passport-user-compare/model"
"go-common/library/log"
"github.com/go-sql-driver/mysql"
"github.com/pkg/errors"
)
func (s *Service) fullFixed(msg chan *model.ErrorFix) {
for {
fix, ok := <-msg
if !ok {
log.Error("consumer full info closed")
return
}
log.Info("full data fixed consumer msg,(%+v)", fix)
if s.c.DataFixSwitch {
errType := fix.ErrorType
if notExistUserBase == errType || pwdErrorType == errType || statusErrorType == errType || statusErrorType == userIDErrorType {
s.fixUserBase(fix.Mid, fix.Action, "full")
}
if notExistUserTel == errType || telErrorType == errType {
s.fixUserTel(fix.Mid, fix.Action, "full")
}
if notExistUserMail == errType || mailErrorType == errType {
s.fixUserMail(fix.Mid, fix.Action, "full")
}
if notExistUserSafeQuestion == errType || safeErrorType == errType {
s.fixSafeQuestion(fix.Mid, fix.Action, "full")
}
if notExistUserThirdBind == errType || sinaErrorType == errType || qqErrorType == errType {
s.fixUserSns(fix.Mid, errType, fix.Action, "full")
}
}
}
}
func (s *Service) incFixed(msg chan *model.ErrorFix) {
for {
fix, ok := <-msg
if !ok {
log.Error("consumer inc info closed")
return
}
log.Info("dynamic data fixed consumer msg,(%+v)", fix)
if s.incrDataFixSwitch {
errType := fix.ErrorType
if notExistUserBase == errType || pwdErrorType == errType || statusErrorType == errType || statusErrorType == userIDErrorType {
s.fixUserBase(fix.Mid, fix.Action, "incr")
}
if notExistUserTel == errType || telErrorType == errType {
s.fixUserTel(fix.Mid, fix.Action, "incr")
}
if notExistUserMail == errType || mailErrorType == errType {
s.fixUserMail(fix.Mid, fix.Action, "incr")
}
if notExistUserSafeQuestion == errType || safeErrorType == errType {
s.fixSafeQuestion(fix.Mid, fix.Action, "incr")
}
if notExistUserThirdBind == errType || sinaErrorType == errType || qqErrorType == errType {
s.fixUserSns(fix.Mid, errType, fix.Action, "incr")
}
if notExistUserRegOriginType == errType || userRegOriginErrorType == errType {
s.fixUserRegOrigin(fix.Mid, errType, fix.Action, "incr")
}
}
}
}
func (s *Service) fixUserBase(mid int64, action, tpe string) {
var (
origin *model.OriginAccount
err error
)
log.Info("data fix user base,mid is %d,action %s,type %s", mid, action, tpe)
if origin, err = s.d.QueryAccountByMid(context.Background(), mid); err != nil {
log.Error("data fix query account by mid error,mid is %d,err is (%+v)", mid, err)
return
}
var pwdByte []byte
if pwdByte, err = hex.DecodeString(origin.Pwd); err != nil {
log.Error("data fix hex.DecodeString(origin.Pwd) error,mid is %d,err is (%+v),origin is(%+v)", mid, err, origin)
return
}
if insertAction == action {
a := &model.UserBase{
Mid: origin.Mid,
UserID: origin.UserID,
Pwd: pwdByte,
Salt: origin.Salt,
Status: origin.Isleak,
Deleted: 0,
MTime: origin.MTime,
}
if _, err = s.d.InsertUserBase(context.Background(), a); err != nil {
log.Error("data fix s.d.InsertUserBase by mid error,mid is %d,err is (%+v)", mid, err)
return
}
}
if updateAction == action {
a := &model.UserBase{
Mid: origin.Mid,
UserID: origin.UserID,
Pwd: pwdByte,
Salt: origin.Salt,
Status: origin.Isleak,
}
if _, err = s.d.UpdateUserBase(context.Background(), a); err != nil {
log.Error("data fix s.d.UpdateUserBase by mid error,mid is %d,err is (%+v)", mid, err)
return
}
}
}
func (s *Service) fixUserTel(mid int64, action, tpe string) {
var (
origin *model.OriginAccount
err error
)
log.Info("data fix user tel,mid is %d,action %s,type %s", mid, action, tpe)
if origin, err = s.d.QueryAccountByMid(context.Background(), mid); err != nil {
log.Error("data fix query account by mid error,mid is %d,err is (%+v)", mid, err)
return
}
ot := strings.Trim(strings.ToLower(origin.Tel), "")
var telByte []byte
if telByte, err = s.doEncrypt(ot); err != nil {
log.Error("data fix doEncrypt tel by mid error,mid is %d,err is (%+v)", mid, err)
return
}
var telBindTime int64
if insertAction == action && len(ot) != 0 {
ut := &model.UserTel{
Mid: origin.Mid,
Tel: telByte,
Cid: s.countryMap[origin.CountryID],
MTime: origin.MTime,
}
if telBindTime, err = s.d.QueryTelBindLog(context.Background(), mid); err != nil {
log.Error("user not exist tel.mid %d", mid)
}
if telBindTime > int64(filterStart) && telBindTime < int64(filterEnd) {
telBindTime = 0
}
ut.TelBindTime = telBindTime
if _, err = s.d.InsertUserTel(context.Background(), ut); err != nil {
switch nErr := errors.Cause(err).(type) {
case *mysql.MySQLError:
if nErr.Number == mySQLErrCodeDuplicateEntry {
if err = s.handlerInsertTelDuplicate(ut); err != nil {
log.Error("fail to handlerInsertTelDuplicate userTel(%+v) error(%+v)", ut, err)
return
}
err = nil
return
}
}
log.Error("fail to add user tel userTel(%+v) error(%+v)", ut, err)
return
}
}
if updateAction == action {
ut := &model.UserTel{
Mid: origin.Mid,
Tel: telByte,
Cid: s.countryMap[origin.CountryID],
}
if _, err = s.d.UpdateUserTel(context.Background(), ut); err != nil {
switch nErr := errors.Cause(err).(type) {
case *mysql.MySQLError:
if nErr.Number == mySQLErrCodeDuplicateEntry {
if err = s.handlerUpdateTelDuplicate(ut); err != nil {
log.Error("fail to handlerInsertTelDuplicate userTel(%+v) error(%+v)", ut, err)
return
}
err = nil
return
}
}
log.Error("fail to update user tel userTel(%+v) error(%+v)", ut, err)
return
}
}
}
func (s *Service) fixUserMail(mid int64, action, tpe string) {
var (
origin *model.OriginAccount
originInfo *model.OriginAccountInfo
err error
)
if origin, err = s.d.QueryAccountByMid(context.Background(), mid); err != nil {
log.Error("data fix query account by mid error,mid is %d,err is (%+v)", mid, err)
return
}
log.Info("data fix user mail,mid is %d,action %s,type %s, origin(%+v)", mid, action, tpe, origin)
om := strings.Trim(strings.ToLower(origin.Email), "")
var emailByte []byte
if emailByte, err = s.doEncrypt(om); err != nil {
log.Error("data fix doEncrypt mail by mid error,mid is %d,err is (%+v)", mid, err)
return
}
if insertAction == action && len(om) != 0 {
userMail := &model.UserEmail{
Mid: origin.Mid,
Email: emailByte,
MTime: origin.MTime,
}
if originInfo, err = s.d.QueryAccountInfoByMid(context.Background(), mid); err != nil {
log.Error("fail to QueryAccountInfoByMid mid is (%+v) error(%+v)", mid, err)
return
}
timestamp := originInfo.ActiveTime
if originInfo.Spacesta >= 0 {
userMail.Verified = 1
userMail.EmailBindTime = timestamp
}
if _, err = s.d.InsertUserEmail(context.Background(), userMail); err != nil {
switch nErr := errors.Cause(err).(type) {
case *mysql.MySQLError:
if nErr.Number == mySQLErrCodeDuplicateEntry {
if err = s.handlerEmailInsertDuplicate(userMail); err != nil {
log.Error("fail to handlerEmailInsertDuplicate userEmail(%+v) error(%+v)", userMail, err)
return
}
err = nil
return
}
}
log.Error("fail to add user email userEmail(%+v) error(%+v)", userMail, err)
return
}
}
if updateAction == action {
userMail := &model.UserEmail{
Mid: origin.Mid,
Email: emailByte,
}
if _, err = s.d.UpdateUserMail(context.Background(), userMail); err != nil {
switch nErr := errors.Cause(err).(type) {
case *mysql.MySQLError:
if nErr.Number == mySQLErrCodeDuplicateEntry {
if err = s.handlerEmailUpdateDuplicate(userMail); err != nil {
log.Error("fail to handlerEmailDuplicate userEmail(%+v) error(%+v)", userMail, err)
return
}
err = nil
return
}
}
log.Error("fail to update user email userEmail(%+v) error(%+v)", userMail, err)
return
}
}
}
func (s *Service) fixSafeQuestion(mid int64, action, tpe string) {
var (
accountInfo *model.OriginAccountInfo
err error
)
log.Info("data fix safe question,mid is %d,action %s,type %s", mid, action, tpe)
if accountInfo, err = s.d.QueryAccountInfoByMid(context.Background(), mid); err != nil {
log.Error("data fix query account info by mid error,mid is %d,err is (%+v)", mid, err)
return
}
if insertAction == action && len(accountInfo.SafeAnswer) != 0 {
usq := &model.UserSafeQuestion{
Mid: accountInfo.Mid,
SafeQuestion: accountInfo.SafeQuestion,
SafeAnswer: s.doHash(accountInfo.SafeAnswer),
SafeBindTime: time.Now().Unix(),
}
if _, err = s.d.InsertUserSafeQuestion(context.Background(), usq); err != nil {
log.Error("data fix s.d.InsertUserSafeQuestion error,mid is %d,err is (%+v)", mid, err)
return
}
}
if updateAction == action {
usq := &model.UserSafeQuestion{
Mid: accountInfo.Mid,
SafeQuestion: accountInfo.SafeQuestion,
SafeAnswer: s.doHash(accountInfo.SafeAnswer),
}
if _, err = s.d.UpdateUserSafeQuestion(context.Background(), usq); err != nil {
log.Error("data fix s.d.UpdateUserSafeQuestion error,mid is %d,err is (%+v)", mid, err)
return
}
}
}
func (s *Service) fixUserSns(mid, errType int64, action, tpe string) {
var (
accountSns *model.OriginAccountSns
err error
)
log.Info("data fix third bind ,mid is %d,action %s,type %s", mid, action, tpe)
if accountSns, err = s.d.QueryAccountSnsByMid(context.Background(), mid); err != nil {
log.Error("data fix query account sns by mid error,mid is %d,err is (%+v)", mid, err)
return
}
if insertAction == action {
if len(accountSns.SinaAccessToken) != 0 {
sina := &model.UserThirdBind{
Mid: accountSns.Mid,
PlatForm: platformSina,
OpenID: string(accountSns.SinaUID),
Token: accountSns.SinaAccessToken,
Expires: accountSns.SinaAccessExpires,
}
if _, err = s.d.InsertUserThirdBind(context.Background(), sina); err != nil {
log.Error("data fix s.d.InsertUserThirdBind by mid error,mid is %d,err is (%+v)", mid, err)
return
}
}
if len(accountSns.QQAccessToken) != 0 {
qq := &model.UserThirdBind{
Mid: accountSns.Mid,
PlatForm: platformQQ,
OpenID: accountSns.QQOpenid,
Token: accountSns.QQAccessToken,
Expires: accountSns.QQAccessExpires,
}
if _, err = s.d.InsertUserThirdBind(context.Background(), qq); err != nil {
log.Error("data fix s.d.UpdateUserThirdBind by mid error,mid is %d,err is (%+v)", mid, err)
return
}
}
}
if updateAction == action {
if sinaErrorType == errType {
sns := &model.UserThirdBind{
Mid: accountSns.Mid,
PlatForm: platformSina,
OpenID: string(accountSns.SinaUID),
Token: accountSns.SinaAccessToken,
}
if _, err = s.d.UpdateUserThirdBind(context.Background(), sns); err != nil {
log.Error("data fix s.d.UpdateUserThirdBind by mid error,mid is %d,err is (%+v)", mid, err)
return
}
}
if qqErrorType == errType {
sns := &model.UserThirdBind{
Mid: accountSns.Mid,
PlatForm: platformQQ,
OpenID: accountSns.QQOpenid,
Token: accountSns.QQAccessToken,
}
if _, err = s.d.UpdateUserThirdBind(context.Background(), sns); err != nil {
log.Error("data fix s.d.UpdateUserThirdBind by mid error,mid is %d,err is (%+v)", mid, err)
return
}
}
}
}
func (s *Service) fixUserRegOrigin(mid, errType int64, action, tpe string) {
var (
accountInfo *model.OriginAccountInfo
accountReg *model.OriginAccountReg
affected int64
err error
)
log.Info("data fix user reg ,mid is %d,action %s,type %s", mid, action, tpe)
if accountInfo, err = s.d.QueryAccountInfoByMid(context.Background(), mid); err != nil {
log.Error("data fix query account info by mid error,mid is %d,err is (%+v)", mid, err)
return
}
uro := &model.UserRegOrigin{
Mid: accountInfo.Mid,
JoinTime: accountInfo.JoinTime,
JoinIP: InetAtoN(accountInfo.JoinIP),
MTime: accountInfo.MTime,
CTime: accountInfo.MTime,
}
if mid >= 250531100 {
if accountReg, err = s.d.QueryAccountRegByMid(context.Background(), mid); err != nil {
log.Error("data fix query account reg by mid error,mid is %d,err is (%+v)", mid, err)
return
}
if accountReg != nil {
uro.RegType = accountReg.RegType
uro.Origin = accountReg.OriginType
uro.MTime = accountReg.MTime
uro.CTime = accountReg.CTime
uro.AppID = accountReg.AppID
}
}
if insertAction == action || updateAction == action {
if affected, err = s.d.InsertUpdateUserRegOriginType(context.Background(), uro); err != nil {
log.Error("data fix InsertUpdateUserRegOrigin by mid error,mid is %d,err is (%+v)", mid, err)
return
}
if affected == 0 {
log.Error("data fix InsertUpdateUserRegOrigin opt error,not affected ", mid, err)
return
}
}
}
func (s *Service) handlerEmailInsertDuplicate(userEmail *model.UserEmail) (err error) {
var (
duplicateMid int64
asoAccount *model.OriginAccount
affected int64
)
if duplicateMid, err = s.d.GetMidByEmail(context.Background(), userEmail); err != nil {
log.Error("handlerEmailInsertDuplicate fail to get mid by email userEmail(%+v) error(%+v)", userEmail, err)
return
}
if asoAccount, err = s.d.QueryAccountByMid(context.Background(), duplicateMid); err != nil {
log.Error("handlerEmailInsertDuplicate fail to get asoAccount by mid(%d) error(%+v)", duplicateMid, err)
return
}
// 3. 将冲突的Email设置为NULL
dunplicateUserMailToNil := &model.UserEmail{
Mid: duplicateMid,
}
if affected, err = s.d.UpdateUserMail(context.Background(), dunplicateUserMailToNil); err != nil || affected == 0 {
log.Error("handlerEmailInsertDuplicate s.d.UpdateUserMail to nil error.")
}
// 4. 插入新的email
if affected, err = s.d.InsertUserEmail(context.Background(), userEmail); err != nil {
log.Error("handlerEmailInsertDuplicate s.d.InsertUserEmail. userMail is (%+v),affect is %d", userEmail, affected)
}
// 5. 更新的tel
om := strings.Trim(strings.ToLower(asoAccount.Email), "")
var emailByte []byte
if emailByte, err = s.doEncrypt(om); err != nil {
log.Error("handlerEmailInsertDuplicate data fix doEncrypt mail by mid error,mid is %d,err is (%+v)", asoAccount.Mid, err)
return
}
dunplicateUserEmail := &model.UserEmail{
Mid: asoAccount.Mid,
Email: emailByte,
}
if affected, err = s.d.UpdateUserMail(context.Background(), dunplicateUserEmail); err != nil {
log.Error("handlerEmailInsertDuplicate s.d.UpdateUserMail to right. userMail is (%+v),affected is %d", dunplicateUserEmail, affected)
}
return
}
func (s *Service) handlerEmailUpdateDuplicate(userEmail *model.UserEmail) (err error) {
var (
duplicateMid int64
asoAccount *model.OriginAccount
affected int64
)
if duplicateMid, err = s.d.GetMidByEmail(context.Background(), userEmail); err != nil {
log.Error("handlerEmailInsertDuplicate fail to get mid by email userEmail(%+v) error(%+v)", userEmail, err)
return
}
if asoAccount, err = s.d.QueryAccountByMid(context.Background(), duplicateMid); err != nil {
log.Error("handlerEmailInsertDuplicate fail to get asoAccount by mid(%d) error(%+v)", duplicateMid, err)
return
}
// 3. 将冲突的Email设置为NULL
duplicateUserMailToNil := &model.UserEmail{
Mid: duplicateMid,
}
if affected, err = s.d.UpdateUserMail(context.Background(), duplicateUserMailToNil); err != nil || affected == 0 {
log.Error("handlerEmailInsertDuplicate s.d.UpdateUserMail to nil error.")
}
// 4. 插入新的email
if affected, err = s.d.UpdateUserMail(context.Background(), userEmail); err != nil {
log.Error("handlerEmailInsertDuplicate s.d.InsertUserEmail. userMail is (%+v),affected %d", userEmail, affected)
}
// 5. 更新的tel
om := strings.Trim(strings.ToLower(asoAccount.Email), "")
var emailByte []byte
if emailByte, err = s.doEncrypt(om); err != nil {
log.Error("handlerEmailInsertDuplicate data fix doEncrypt mail by mid error,mid is %d,err is (%+v)", asoAccount.Mid, err)
return
}
duplicateUserEmail := &model.UserEmail{
Mid: asoAccount.Mid,
Email: emailByte,
}
if affected, err = s.d.UpdateUserMail(context.Background(), duplicateUserEmail); err != nil {
log.Error("handlerEmailInsertDuplicate s.d.UpdateUserMail to right. userMail is (%+v),affected %d", duplicateUserEmail, affected)
}
return
}
func (s *Service) handlerInsertTelDuplicate(userTel *model.UserTel) (err error) {
var (
duplicateMid int64
duplicateAsoAccount *model.OriginAccount
affected int64
)
// 1. 查询duplicateMid
if duplicateMid, err = s.d.GetMidByTel(context.Background(), userTel); err != nil {
log.Error("handlerInsertTelDuplicate to get mid by tel userTel(%+v) error(%+v)", userTel, err)
return
}
// 2. 查询冲突的mid
if duplicateAsoAccount, err = s.d.QueryAccountByMid(context.Background(), duplicateMid); err != nil {
log.Error("handlerInsertTelDuplicate to get asoAccount by mid(%d) error(%+v)", duplicateMid, err)
return
}
// 3. 将冲突的tel设置为NULL
duplicateUserTelToNil := &model.UserTel{
Mid: duplicateMid,
}
if affected, err = s.d.UpdateUserTel(context.Background(), duplicateUserTelToNil); err != nil || affected == 0 {
log.Error("handlerInsertTelDuplicate s.d.UpdateUserTel to nil error.")
}
// 4. 插入新的tel
if affected, err = s.d.InsertUserTel(context.Background(), userTel); err != nil {
log.Error("handlerInsertTelDuplicate s.d.InsertUserTel.userTel is (%+v),affected %d", userTel, affected)
}
// 5. 更新的tel
ot := strings.Trim(strings.ToLower(duplicateAsoAccount.Tel), "")
var telByte []byte
if telByte, err = s.doEncrypt(ot); err != nil {
log.Error("data fix doEncrypt tel by mid error,mid is %d,err is (%+v)", duplicateAsoAccount.Mid, err)
return
}
duplicateUserTel := &model.UserTel{
Mid: duplicateAsoAccount.Mid,
Cid: s.countryMap[duplicateAsoAccount.CountryID],
Tel: telByte,
}
if affected, err = s.d.UpdateUserTel(context.Background(), duplicateUserTel); err != nil {
log.Error("handlerInsertTelDuplicate s.d.UpdateUserTel to right. userTel is (%+v),affected %d", userTel, affected)
}
return
}
func (s *Service) handlerUpdateTelDuplicate(userTel *model.UserTel) (err error) {
var (
duplicateMid int64
duplicateAsoAccount *model.OriginAccount
affected int64
)
// 1. 查询duplicateMid
if duplicateMid, err = s.d.GetMidByTel(context.Background(), userTel); err != nil {
log.Error("handlerUpdateTelDuplicate to get mid by tel userTel(%+v) error(%+v)", userTel, err)
return
}
// 2. 查询冲突的mid
if duplicateAsoAccount, err = s.d.QueryAccountByMid(context.Background(), duplicateMid); err != nil {
log.Error("handlerUpdateTelDuplicate to get asoAccount by mid(%d) error(%+v)", duplicateMid, err)
return
}
duplicateUserTelToNil := &model.UserTel{
Mid: duplicateMid,
}
// 3. 冲突的Tel设置为NULL
if affected, err = s.d.UpdateUserTel(context.Background(), duplicateUserTelToNil); err != nil || affected == 0 {
log.Error("handlerUpdateTelDuplicate s.d.UpdateUserTel to nil error.")
}
// 4. update tel
if affected, err = s.d.UpdateUserTel(context.Background(), userTel); err != nil {
log.Error("handlerUpdateTelDuplicate s.d.UpdateUserTel.userTel is (%+v),affected %d", userTel, affected)
}
// 5. 设置冲突的tel
ot := strings.Trim(strings.ToLower(duplicateAsoAccount.Tel), "")
var telByte []byte
if telByte, err = s.doEncrypt(ot); err != nil {
log.Error("handlerUpdateTelDuplicate data fix doEncrypt tel by mid error,mid is %d,err is (%+v)", duplicateAsoAccount.Mid, err)
return
}
duplicateUserTel := &model.UserTel{
Mid: duplicateAsoAccount.Mid,
Cid: s.countryMap[duplicateAsoAccount.CountryID],
Tel: telByte,
}
if affected, err = s.d.UpdateUserTel(context.Background(), duplicateUserTel); err != nil {
log.Error("handlerUpdateTelDuplicate s.d.UpdateUserTel to right. userTel is (%+v),affected %d", userTel, affected)
}
return
}
func (s *Service) fixEmailVerified() (err error) {
var (
res []*model.UserEmail
originInfo *model.OriginAccountInfo
start = int64(0)
)
for {
log.Info("GetUnverifiedEmail, start %d", start)
if res, err = s.d.GetUnverifiedEmail(context.Background(), start); err != nil {
log.Error("fail to get UserTel error(%+v)", err)
time.Sleep(100 * time.Millisecond)
continue
}
if len(res) == 0 {
log.Info("fix email verified finished!")
break
}
for _, a := range res {
for {
if originInfo, err = s.d.QueryAccountInfoByMid(context.Background(), a.Mid); err != nil {
log.Error("fail to QueryAccountInfoByMid mid is (%+v) error(%+v)", a.Mid, err)
continue
}
break
}
if originInfo.Spacesta >= 0 {
a.Verified = 1
_, err = s.d.UpdateUserMailVerified(context.Background(), a)
}
}
start = res[len(res)-1].Mid
}
return
}

View File

@@ -0,0 +1,90 @@
package service
import (
"context"
"encoding/hex"
"strings"
"go-common/app/job/main/passport-user-compare/model"
"go-common/library/log"
)
func (s *Service) checkTelDuplicateJob() {
log.Info("check tel duplicate job start...")
res, err := s.d.UserTelDuplicate(context.Background())
if err != nil {
log.Error("fail to get UserTelDuplicate, error(%+v)", err)
return
}
var (
asoAccount *model.OriginAccount
userTel *model.UserTel
)
for _, r := range res {
if asoAccount, err = s.d.QueryAccountByMid(context.Background(), r.Mid); err != nil {
log.Error("fail to check tel duplicate mid(%d) error(%+v)", r.Mid, err)
return
}
if userTel, err = s.d.QueryUserTel(context.Background(), r.Mid); err != nil {
log.Error("fail to check tel duplicate mid(%d) error(%+v)", r.Mid, err)
return
}
om := strings.Trim(strings.ToLower(asoAccount.Tel), "")
var telByte []byte
if telByte, err = s.doEncrypt(om); err != nil {
log.Error("checkTelDuplicateJob doEncrypt mail by mid error,mid is %d,err is (%+v)", r.Mid, err)
return
}
originHex := hex.EncodeToString(telByte)
newHex := hex.EncodeToString(userTel.Tel)
if originHex == newHex {
log.Info("check user tel duplicate success, userTelDuplicate(%+v)", r)
if _, err = s.d.UpdateUserTelDuplicateStatus(context.Background(), r.ID); err != nil {
log.Error("fail to update user tel duplicate status, id(%d) error(%+v)", r.ID, err)
}
} else {
log.Info("fail to check user tel duplicate, new(%s) origin(%s) userTelDuplicate(%+v)", newHex, originHex, r)
}
}
log.Info("update tel duplicate job end...")
}
func (s *Service) checkEmailDuplicateJob() {
log.Info("check email duplicate job start...")
res, err := s.d.UserEmailDuplicate(context.Background())
if err != nil {
log.Error("fail to get UserEmailDuplicate, error(%+v)", err)
return
}
var (
asoAccount *model.OriginAccount
userEmail *model.UserEmail
)
for _, r := range res {
if asoAccount, err = s.d.QueryAccountByMid(context.Background(), r.Mid); err != nil {
log.Error("fail to check email duplicate mid(%d) error(%+v)", r.Mid, err)
return
}
if userEmail, err = s.d.QueryUserMail(context.Background(), r.Mid); err != nil {
log.Error("fail to check email duplicate mid(%d) error(%+v)", r.Mid, err)
return
}
om := strings.Trim(strings.ToLower(asoAccount.Email), "")
var emailByte []byte
if emailByte, err = s.doEncrypt(om); err != nil {
log.Error("checkEmailDuplicateJob doEncrypt mail by mid error,mid is %d,err is (%+v)", r.Mid, err)
return
}
originHex := hex.EncodeToString(emailByte)
newHex := hex.EncodeToString(userEmail.Email)
if originHex == newHex {
log.Info("check user email duplicate success, userEmailDuplicate(%+v)", r)
if _, err = s.d.UpdateUserEmailDuplicateStatus(context.Background(), r.ID); err != nil {
log.Error("fail to update user email duplicate status, id(%d) error(%+v)", r.ID, err)
}
} else {
log.Info("fail to check user email duplicate, new(%s) origin(%s) userEmailDuplicate(%+v)", newHex, originHex, r)
}
}
log.Info("update email duplicate job end...")
}

View File

@@ -0,0 +1,355 @@
package service
import (
"context"
"encoding/hex"
"strings"
"time"
"go-common/app/job/main/passport-user-compare/model"
"go-common/library/log"
)
// Dynamic inc fixed data
func (s *Service) incCompareAndFix() {
startTime, err := time.ParseInLocation(timeFormat, s.c.IncTask.StartTime, loc)
if err != nil {
log.Error("failed to parse end time, time.ParseInLocation(%s, %s, %v), error(%v)", timeFormat, s.c.IncTask.StartTime, loc, err)
return
}
log.Info("start inc compare and fixed")
for {
stepDuration := time.Duration(s.c.IncTask.StepDuration)
endTime := startTime.Add(stepDuration)
if time.Now().Before(endTime) {
log.Info("break dynamic ")
break
}
s.compareAndFixedUserBaseInc(context.Background(), startTime, endTime)
s.compareAndFixedSafeQuestionInc(context.Background(), startTime, endTime)
s.compareAndFixedUserRegOriginInc(context.Background(), startTime, endTime)
startTime = endTime
endTime = startTime.Add(stepDuration)
}
if len(dynamicAccountStat) != 0 {
if err = s.d.SendWechat(dynamicAccountStat); err != nil {
log.Error("s.d.SendWeChat account stat,error is (%+v)", err)
return
}
}
if len(dynamicAccountInfoStat) != 0 {
if err := s.d.SendWechat(dynamicAccountInfoStat); err != nil {
log.Error("s.d.SendWeChat account info stat ,error is (%+v)", err)
return
}
}
if len(dynamicAccountRegStat) != 0 {
if err := s.d.SendWechat(dynamicAccountRegStat); err != nil {
log.Error("s.d.SendWeChat account reg stat ,error is (%+v)", err)
return
}
}
log.Info("dynamic compare and fix ,chan size is %d", len(s.incFixChan))
}
func (s *Service) compareAndFixedUserBaseInc(c context.Context, start, end time.Time) {
var (
originAccounts []*model.OriginAccount
origin *model.OriginAccount
err error
)
log.Info("dynamic compare and fix user base,tel,mail ,time start is(%+v), end time is (%+v)", start, end)
if originAccounts, err = s.d.BatchQueryAccountByTime(c, start, end); err != nil {
log.Error("dynamic query batch account inc error,error is (%+v)", err)
return
}
for _, originAccount := range originAccounts {
for {
mid := originAccount.Mid
var userBase *model.UserBase
if userBase, err = s.d.QueryUserBase(c, mid); err != nil {
log.Error("dynamic query user base error,mid is %d,err is(+v)", mid, err)
continue
}
// 对比密码和盐
if userBase == nil {
log.Info("dynamic user base not exist,mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserBase, Action: insertAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountStat["notExistUserBase"] = dynamicAccountStat["notExistUserBase"] + 1
s.mu.Unlock()
continue
}
if originAccount.UserID != userBase.UserID {
if origin, err = s.d.QueryAccountByMid(context.Background(), mid); err != nil {
continue
}
if origin.UserID != userBase.UserID {
log.Info("dynamic pwd compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, originAccount.Pwd, hex.EncodeToString(userBase.Pwd))
errorFix := &model.ErrorFix{Mid: mid, ErrorType: userIDErrorType, Action: updateAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountStat["userid"] = dynamicAccountStat["userid"] + 1
s.mu.Unlock()
}
}
if originAccount.Pwd != hex.EncodeToString(userBase.Pwd) || originAccount.Salt != userBase.Salt {
if origin, err = s.d.QueryAccountByMid(context.Background(), mid); err != nil {
continue
}
if origin.Pwd != hex.EncodeToString(userBase.Pwd) || origin.Salt != userBase.Salt {
log.Info("dynamic pwd compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, originAccount.Pwd, hex.EncodeToString(userBase.Pwd))
errorFix := &model.ErrorFix{Mid: mid, ErrorType: pwdErrorType, Action: updateAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountStat["pwd"] = dynamicAccountStat["pwd"] + 1
s.mu.Unlock()
}
}
if originAccount.Isleak != userBase.Status {
if origin, err = s.d.QueryAccountByMid(context.Background(), mid); err != nil {
continue
}
if origin.Isleak != userBase.Status {
log.Info("dynamic status compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, originAccount.Isleak, userBase.Status)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: statusErrorType, Action: updateAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountStat["status"] = dynamicAccountStat["status"] + 1
s.mu.Unlock()
}
}
// 对比手机号
var userTel *model.UserTel
if userTel, err = s.d.QueryUserTel(c, mid); err != nil {
log.Error("dynamic query user tel error,mid is %d,err is(+v)", mid, err)
continue
}
originTel := originAccount.Tel
if originTel != "" && userTel == nil {
log.Info("dynamic tel not exist,mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserTel, Action: insertAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountStat["notExistUserTel"] = dynamicAccountStat["notExistUserTel"] + 1
s.mu.Unlock()
continue
}
if userTel != nil {
var tel string
if tel, err = s.doDecrypt(userTel.Tel); err != nil {
log.Error("dynamic doDecrypt tel error,mid is %d,tel is (%+v), err is(+v)", mid, userTel.Tel, err)
continue
}
ot := strings.Trim(strings.ToLower(originTel), "")
if ot != tel {
if origin, err = s.d.QueryAccountByMid(context.Background(), mid); err != nil {
continue
}
ot = strings.Trim(strings.ToLower(origin.Tel), "")
if ot != tel {
log.Info("dynamic tel compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, ot, tel)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: telErrorType, Action: updateAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountStat["tel"] = dynamicAccountStat["tel"] + 1
s.mu.Unlock()
}
}
}
// 对比邮箱
var userEmail *model.UserEmail
if userEmail, err = s.d.QueryUserMail(c, mid); err != nil {
log.Error("dynamic query user mail error,error is (%+v)", err)
continue
}
originMail := originAccount.Email
if originMail != "" && userEmail == nil {
log.Info("dynamic mail not exist,mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserMail, Action: insertAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountStat["notExistUserMail"] = dynamicAccountStat["notExistUserMail"] + 1
s.mu.Unlock()
continue
}
if userEmail != nil {
var mail string
if mail, err = s.doDecrypt(userEmail.Email); err != nil {
log.Error("dynamic doDecrypt email error,mid is %d,email is (%+v), err is(+v)", mid, userEmail.Email, err)
continue
}
om := strings.Trim(strings.ToLower(originMail), "")
if om != mail {
if origin, err = s.d.QueryAccountByMid(context.Background(), mid); err != nil {
continue
}
om = strings.Trim(strings.ToLower(origin.Email), "")
if om != mail {
log.Info("dynamic mail compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, om, mail)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: mailErrorType, Action: updateAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountStat["mail"] = dynamicAccountStat["mail"] + 1
s.mu.Unlock()
}
}
}
break
}
}
s.mu.Lock()
dynamicAccountStat["dynamicUserBase"] = 0
s.mu.Unlock()
}
func (s *Service) compareAndFixedSafeQuestionInc(c context.Context, start, end time.Time) {
for i := 0; i < 30; i++ {
var (
err error
originAccountInfos []*model.OriginAccountInfo
originInfo *model.OriginAccountInfo
)
log.Info("dynamic compare and fix safe ,time start is(%+v), end time is (%+v)", start, end)
if originAccountInfos, err = s.d.BatchQueryAccountInfoByTime(c, start, end, i); err != nil {
log.Error("dynamic query batch account info inc error,error is (%+v)", err)
return
}
for _, originAccountInfo := range originAccountInfos {
for {
mid := originAccountInfo.Mid
// fixed userSafeQuestion
var userSafeQuestion *model.UserSafeQuestion
if userSafeQuestion, err = s.d.QueryUserSafeQuestion(c, mid); err != nil {
log.Error("dynamic query user safe question err, mid is %d,err is(+v)", mid, err)
continue
}
if len(originAccountInfo.SafeAnswer) == 0 && userSafeQuestion == nil {
continue
}
if len(originAccountInfo.SafeAnswer) != 0 && userSafeQuestion == nil {
log.Info("dynamic safe question not exist, mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserSafeQuestion, Action: insertAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountInfoStat["notExistUserSafeQuestion"] = dynamicAccountInfoStat["notExistUserSafeQuestion"] + 1
s.mu.Unlock()
continue
}
originSafeQuestion := originAccountInfo.SafeQuestion
newSafeQuestion := userSafeQuestion.SafeQuestion
if originSafeQuestion != newSafeQuestion {
if originInfo, err = s.d.QueryAccountInfoByMid(context.Background(), mid); err != nil {
continue
}
if originInfo.SafeQuestion != newSafeQuestion {
log.Info("dynamic safe question index compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, originSafeQuestion, newSafeQuestion)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: safeErrorType, Action: updateAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountInfoStat["safe"] = dynamicAccountInfoStat["safe"] + 1
s.mu.Unlock()
continue
}
}
originSafeAnswerBytes := s.doHash(originAccountInfo.SafeAnswer)
if hex.EncodeToString(originSafeAnswerBytes) != hex.EncodeToString(userSafeQuestion.SafeAnswer) {
if originInfo, err = s.d.QueryAccountInfoByMid(context.Background(), mid); err != nil {
continue
}
if hex.EncodeToString(s.doHash(originAccountInfo.SafeAnswer)) != hex.EncodeToString(userSafeQuestion.SafeAnswer) {
log.Info("dynamic safe question answer compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, originAccountInfo.SafeAnswer, hex.EncodeToString(userSafeQuestion.SafeAnswer))
errorFix := &model.ErrorFix{Mid: mid, ErrorType: safeErrorType, Action: updateAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountInfoStat["safe"] = dynamicAccountInfoStat["safe"] + 1
s.mu.Unlock()
continue
}
}
var uro *model.UserRegOrigin
if uro, err = s.d.GetUserRegOriginByMid(c, mid); err != nil {
log.Error("dynamic query user reg origin err, mid is %d,err is(+v)", mid, err)
continue
}
if uro == nil {
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserRegOriginType, Action: insertAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountRegStat["notExistUserRegOrigin"] = dynamicAccountRegStat["notExistUserRegOrigin"] + 1
s.mu.Unlock()
continue
}
if uro.JoinIP != InetAtoN(originAccountInfo.JoinIP) || uro.JoinTime != originAccountInfo.JoinTime {
if originInfo, err = s.d.QueryAccountInfoByMid(context.Background(), mid); err != nil {
continue
}
if uro.JoinIP != InetAtoN(originInfo.JoinIP) || uro.JoinTime != originInfo.JoinTime {
errorFix := &model.ErrorFix{Mid: mid, ErrorType: userRegOriginErrorType, Action: updateAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountRegStat["userRegOrigin"] = dynamicAccountRegStat["userRegOrigin"] + 1
s.mu.Unlock()
continue
}
}
break
}
}
}
s.mu.Lock()
dynamicAccountInfoStat["dynamicUserSafeQuestion"] = 0
s.mu.Unlock()
}
func (s *Service) compareAndFixedUserRegOriginInc(c context.Context, start, end time.Time) {
for i := 0; i < 20; i++ {
var (
err error
originAccountRegs []*model.OriginAccountReg
)
log.Info("dynamic compare and fix account origin reg ,time start is(%+v), end time is (%+v)", start, end)
if originAccountRegs, err = s.d.BatchQueryAccountRegByTime(c, start, end, i); err != nil {
log.Error("dynamic query batch account info inc error,error is (%+v)", err)
return
}
for _, originAccountReg := range originAccountRegs {
mid := originAccountReg.Mid
// fixed userSafeQuestion
var uro *model.UserRegOrigin
if uro, err = s.d.GetUserRegOriginByMid(c, mid); err != nil {
log.Error("dynamic query user reg origin err, mid is %d,err is(+v)", mid, err)
continue
}
if uro == nil {
log.Info("dynamic user reg origin not exist, mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserRegOriginType, Action: insertAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountRegStat["notExistUserRegOrigin"] = dynamicAccountRegStat["notExistUserRegOrigin"] + 1
s.mu.Unlock()
continue
}
if mid <= 250531100 {
continue
}
if uro.RegType != originAccountReg.RegType || uro.Origin != originAccountReg.OriginType {
log.Info("dynamic user reg origin update, mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: userRegOriginErrorType, Action: updateAction}
s.incFixChan <- errorFix
s.mu.Lock()
dynamicAccountRegStat["userRegOrigin"] = dynamicAccountRegStat["userRegOrigin"] + 1
s.mu.Unlock()
continue
}
}
}
s.mu.Lock()
dynamicAccountRegStat["dynamicUserRegOrigin"] = 0
s.mu.Unlock()
}

View File

@@ -0,0 +1,302 @@
package service
import (
"context"
"encoding/hex"
"strconv"
"strings"
"go-common/app/job/main/passport-user-compare/model"
"go-common/library/log"
)
// full compare data and fix data
func (s *Service) fullCompareAndFix() {
go s.compareAndFixedUserBase(context.Background())
go s.compareAndFixedSafeQuestion(context.Background())
go s.compareAndFixedSns(context.Background())
}
// full div compare and fixed use base info .
func (s *Service) compareAndFixedUserBase(c context.Context) {
diff := s.c.FullTask.AccountEnd / fullDivSegment
var i int64
for i = 0; i < fullDivSegment; i++ {
go s.compareAndFixedUserBaseDiv(context.Background(), i, diff*i, diff*(i+1))
}
}
// full div compare safe question .
func (s *Service) compareAndFixedSafeQuestion(c context.Context) {
for i := 0; i < 30; i++ {
go s.compareAndFixedSafeQuestionDiv(context.Background(), i)
}
}
// full div compare and fixed sns.
func (s *Service) compareAndFixedSns(c context.Context) {
diff := s.c.FullTask.AccountSnsEnd / fullDivSegment
var i int64
for i = 0; i < fullDivSegment; i++ {
go s.compareAndFixSnsDiv(context.Background(), i, diff*i, diff*(i+1))
}
}
func (s *Service) compareAndFixedUserBaseDiv(c context.Context, index, start, end int64) {
var (
originAccounts []*model.OriginAccount
err error
)
for {
log.Info("start full compare basic_account,index %d,start is %d ,end is %d ,step is %d ", index, start, end, s.c.FullTask.Step)
if originAccounts, err = s.d.BatchQueryAccount(c, start, s.c.FullTask.Step); err != nil {
log.Error("query batch account error,error is (%+v)", err)
continue
}
for _, originAccount := range originAccounts {
mid := originAccount.Mid
// 密码、状态对比
var userBase *model.UserBase
if userBase, err = s.d.QueryUserBase(c, mid); err != nil {
log.Error("full query user base error,mid is %d,err is(+v)", mid, err)
continue
}
if userBase == nil {
log.Info("full userBase not exist,mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserBase, Action: insertAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountStat["notExistUserBase"] = accountStat["notExistUserBase"] + 1
s.mu.Unlock()
continue
}
if originAccount.Pwd != hex.EncodeToString(userBase.Pwd) || originAccount.Salt != userBase.Salt {
log.Info("full pwd compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, originAccount.Pwd, hex.EncodeToString(userBase.Pwd))
errorFix := &model.ErrorFix{Mid: mid, ErrorType: pwdErrorType, Action: updateAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountStat["pwd"] = accountStat["pwd"] + 1
s.mu.Unlock()
}
if originAccount.Isleak != userBase.Status {
log.Info("full status compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, originAccount.Isleak, userBase.Status)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: statusErrorType, Action: updateAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountStat["status"] = accountStat["status"] + 1
s.mu.Unlock()
}
// 对比手机号
var userTel *model.UserTel
if userTel, err = s.d.QueryUserTel(c, mid); err != nil {
log.Error("full query user tel error,mid is %d,err is(+v)", mid, err)
continue
}
originTel := originAccount.Tel
if originTel != "" && userTel == nil {
log.Info("dynamic tel not exist,mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserTel, Action: insertAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountStat["notExistUserTel"] = accountStat["notExistUserTel"] + 1
s.mu.Unlock()
continue
}
if userTel != nil {
var tel string
if tel, err = s.doDecrypt(userTel.Tel); err != nil {
log.Error("full doDecrypt tel error,mid is %d,tel is (%+v), err is(+v)", mid, userTel.Tel, err)
continue
}
ot := strings.Trim(strings.ToLower(originTel), "")
if ot != tel {
log.Info("full tel compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, ot, tel)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: telErrorType, Action: updateAction}
s.fullFixChan <- errorFix
s.mu.Lock()
dynamicAccountStat["tel"] = dynamicAccountStat["tel"] + 1
s.mu.Unlock()
}
}
// 对比邮箱
var userEmail *model.UserEmail
if userEmail, err = s.d.QueryUserMail(c, mid); err != nil {
log.Error("full query user mail error,error is (%+v)", err)
continue
}
originMail := originAccount.Email
if originMail != "" && userEmail == nil {
log.Info("full mail not exist,mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserMail, Action: insertAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountStat["notExistUserMail"] = accountStat["notExistUserMail"] + 1
s.mu.Unlock()
continue
}
if userEmail != nil {
var mail string
if mail, err = s.doDecrypt(userEmail.Email); err != nil {
log.Error("full doDecrypt email error,mid is %d,email is (%+v), err is(+v)", mid, userEmail.Email, err)
continue
}
om := strings.Trim(strings.ToLower(originMail), "")
if om != mail {
log.Info("full mail compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, originMail, mail)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: mailErrorType, Action: updateAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountStat["mail"] = accountStat["mail"] + 1
s.mu.Unlock()
}
}
}
if start > end || len(originAccounts) == 0 {
break
}
start = originAccounts[len(originAccounts)-1].Mid
}
log.Info("End full compare basic_account,index %d ", index)
s.mu.Lock()
accountStat["user_base_index"] = index
s.mu.Unlock()
if err = s.d.SendWechat(accountStat); err != nil {
log.Error("s.d.SendWechat account stat,error is (%+v)", err)
return
}
}
func (s *Service) compareAndFixedSafeQuestionDiv(c context.Context, tableIndex int) {
var (
start int64
err error
)
for {
log.Info("start full compare aso_account_info,table is %d,start is %d,step is %d", tableIndex, start, s.c.FullTask.Step)
var originAccountInfos []*model.OriginAccountInfo
if originAccountInfos, err = s.d.BatchQueryAccountInfo(c, start, s.c.FullTask.Step, tableIndex); err != nil {
log.Error("full query batch account info error,error is (%+v)", err)
continue
}
for _, originAccountInfo := range originAccountInfos {
mid := originAccountInfo.Mid
if len(originAccountInfo.SafeAnswer) != 0 {
var userSafeQuestion *model.UserSafeQuestion
if userSafeQuestion, err = s.d.QueryUserSafeQuestion(c, mid); err != nil {
log.Error("full query user safe question err, mid is %d,err is(+v)", mid, err)
continue
}
if userSafeQuestion == nil {
log.Info("full userSafeQuestion not exist,mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserSafeQuestion, Action: insertAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountInfoStat["notExistUserSafeQuestion"] = accountInfoStat["notExistUserSafeQuestion"] + 1
s.mu.Unlock()
continue
}
originSafeAnswerBytes := s.doHash(originAccountInfo.SafeAnswer)
if hex.EncodeToString(originSafeAnswerBytes) != hex.EncodeToString(userSafeQuestion.SafeAnswer) {
log.Info("full safe question compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, originAccountInfo.SafeAnswer, hex.EncodeToString(userSafeQuestion.SafeAnswer))
errorFix := &model.ErrorFix{Mid: mid, ErrorType: safeErrorType, Action: updateAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountInfoStat["safe"] = accountInfoStat["safe"] + 1
s.mu.Unlock()
}
}
}
if start > s.c.FullTask.AccountInfoEnd || len(originAccountInfos) == 0 {
break
}
start = originAccountInfos[len(originAccountInfos)-1].ID
}
log.Info("end full compare and fix account info table is %d", tableIndex)
s.mu.Lock()
accountInfoStat["user_safe_question_index"] = int64(tableIndex)
s.mu.Unlock()
if err := s.d.SendWechat(accountInfoStat); err != nil {
log.Error("s.d.SendWeChat account info stat ,error is (%+v)", err)
return
}
}
func (s *Service) compareAndFixSnsDiv(c context.Context, index, start, end int64) {
var err error
for {
log.Info("start full compare aso_account_sns,index is %d,start is %d,step is %d", index, start, s.c.FullTask.Step)
var originAccountSnses []*model.OriginAccountSns
if originAccountSnses, err = s.d.BatchQueryAccountSns(c, start, s.c.FullTask.Step); err != nil {
log.Error("full query batch account sns error,error is (%+v)", err)
continue
}
for _, sns := range originAccountSnses {
mid := sns.Mid
if sns.QQOpenid != "" {
var userThirdBind *model.UserThirdBind
if userThirdBind, err = s.d.QueryUserThirdBind(c, mid, platformQQ); err != nil {
log.Error("full query user bind error ,mid is %d, error is %(+v)", mid, err)
continue
}
if userThirdBind == nil {
log.Info("full sns not exist,mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserThirdBind, Action: insertAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountSnsStat["notExistUserThirdBind"] = accountSnsStat["notExistUserThirdBind"] + 1
s.mu.Unlock()
continue
}
if userThirdBind.PlatForm == 2 && userThirdBind.OpenID != sns.QQOpenid {
log.Info("full sns qq compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, string(sns.QQOpenid), userThirdBind.OpenID)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: qqErrorType, Action: updateAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountSnsStat["sns"] = accountSnsStat["sns"] + 1
s.mu.Unlock()
}
}
if sns.SinaUID != 0 {
var userThirdBind *model.UserThirdBind
if userThirdBind, err = s.d.QueryUserThirdBind(c, mid, platformSina); err != nil {
log.Error("full query user bind error ,mid is %d, error is %(+v)", mid, err)
continue
}
if userThirdBind == nil {
log.Info("full sns not exist,mid is %d", mid)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: notExistUserThirdBind, Action: insertAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountSnsStat["notExistUserThirdBind"] = accountSnsStat["notExistUserThirdBind"] + 1
s.mu.Unlock()
continue
}
var openID int64
if openID, err = strconv.ParseInt(userThirdBind.OpenID, 10, 64); err != nil {
log.Error("parse error.")
return
}
if userThirdBind.PlatForm == 1 && openID != sns.SinaUID {
log.Info("full sns sina compare not match,mid is %d, origin is (%+v),new is (%+v)", mid, sns.SinaUID, userThirdBind.OpenID)
errorFix := &model.ErrorFix{Mid: mid, ErrorType: sinaErrorType, Action: updateAction}
s.fullFixChan <- errorFix
s.mu.Lock()
accountSnsStat["sns"] = accountSnsStat["sns"] + 1
s.mu.Unlock()
}
}
}
if start > end || len(originAccountSnses) == 0 {
break
}
start = originAccountSnses[len(originAccountSnses)-1].Mid
}
log.Info("end full compare and fix account sns index %d", index)
s.mu.Lock()
accountSnsStat["user_sns_index"] = index
s.mu.Unlock()
if err = s.d.SendWechat(accountSnsStat); err != nil {
log.Error("s.d.SendWeChat sns stat,error is (%+v)", err)
return
}
}

View File

@@ -0,0 +1,162 @@
package service
import (
"context"
"sync"
"time"
"go-common/app/job/main/passport-user-compare/conf"
"go-common/app/job/main/passport-user-compare/dao"
"go-common/app/job/main/passport-user-compare/model"
"go-common/library/log"
"github.com/robfig/cron"
)
const (
publicKeyConst int8 = 0
privateKeyConst int8 = 1
aesKeyConst int8 = 2
md5KeyConst int8 = 3
timeFormat = "2006-01-02 15:04:05"
pwdErrorType = 1
statusErrorType = 2
telErrorType = 3
mailErrorType = 4
safeErrorType = 5
sinaErrorType = 6
qqErrorType = 7
notExistUserBase = 8
notExistUserTel = 9
notExistUserMail = 10
notExistUserSafeQuestion = 11
notExistUserThirdBind = 12
userIDErrorType = 13
notExistUserRegOriginType = 14
userRegOriginErrorType = 15
insertAction = "insert"
updateAction = "update"
fullDivSegment int64 = 10
platformSina int64 = 1
platformQQ int64 = 2
filterStart int64 = 1536572121
filterEnd int64 = 1536616436
mySQLErrCodeDuplicateEntry = 1062
)
var (
privateKey = ""
publicKey = ""
aesKey = ""
md5slat = ""
dynamicAccountStat = make(map[string]int64, 7)
dynamicAccountInfoStat = make(map[string]int64, 2)
dynamicAccountRegStat = make(map[string]int64, 2)
accountStat = make(map[string]int64, 7)
accountInfoStat = make(map[string]int64, 2)
accountSnsStat = make(map[string]int64, 3)
loc = time.Now().Location()
)
// Service service.
type Service struct {
c *conf.Config
d *dao.Dao
cron *cron.Cron
fullFixChan chan *model.ErrorFix
incFixChan chan *model.ErrorFix
mu sync.Mutex
countryMap map[int64]string
dataFixSwitch bool
incrDataFixSwitch bool
}
// New new service
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
d: dao.New(c),
cron: cron.New(),
dataFixSwitch: c.DataFixSwitch,
incrDataFixSwitch: c.IncrDataFixSwitch,
fullFixChan: make(chan *model.ErrorFix, 1024),
incFixChan: make(chan *model.ErrorFix, 2048),
}
var err error
s.countryMap, err = s.d.QueryCountryCode(context.Background())
if err != nil || len(s.countryMap) == 0 {
log.Error("fail to get country map")
panic(err)
}
s.initSecret()
if s.c.FullTask.Switch {
log.Info("start full compare and fixed")
go s.fullFixed(s.fullFixChan)
if err := s.cron.AddFunc(s.c.FullTask.CronFullStr, s.fullCompareAndFix); err != nil {
panic(err)
}
s.cron.Start()
}
if s.c.IncTask.Switch {
log.Info("start inc compare and fixed")
go s.incFixed(s.incFixChan)
if err := s.cron.AddFunc(s.c.IncTask.CronIncStr, s.incCompareAndFix); err != nil {
panic(err)
}
s.cron.Start()
}
if s.c.DuplicateTask.Switch {
log.Info("start check duplicate job")
if err := s.cron.AddFunc(s.c.DuplicateTask.DuplicateCron, s.checkEmailDuplicateJob); err != nil {
panic(err)
}
if err := s.cron.AddFunc(s.c.DuplicateTask.DuplicateCron, s.checkTelDuplicateJob); err != nil {
panic(err)
}
s.cron.Start()
}
if s.c.FixEmailVerifiedSwitch {
go s.fixEmailVerified()
}
return s
}
// Ping check server ok.
func (s *Service) Ping(c context.Context) (err error) {
return
}
// Close close service, including databus and outer service.
func (s *Service) Close() (err error) {
if err = s.d.Close(); err != nil {
panic(err)
}
return
}
func (s *Service) initSecret() {
res, err := s.d.LoadSecret(context.Background())
if err != nil {
panic(err)
}
for _, r := range res {
if publicKeyConst == r.KeyType {
publicKey = r.Key
}
if privateKeyConst == r.KeyType {
privateKey = r.Key
}
if aesKeyConst == r.KeyType {
aesKey = r.Key
}
if md5KeyConst == r.KeyType {
md5slat = r.Key
}
}
if len(aesKey) == 0 {
panic("load secret error")
}
}

View File

@@ -0,0 +1,55 @@
package service
import (
"crypto/md5"
"math/big"
"net"
)
func (s *Service) doEncrypt(param string) ([]byte, error) {
var (
err error
res = make([]byte, 0)
)
if len(param) == 0 {
return res, nil
}
input := []byte(param)
if res, err = Encrypt(input, []byte(aesKey)); err != nil {
return nil, nil
}
return res, nil
}
func (s *Service) doDecrypt(param []byte) (string, error) {
var (
err error
res = make([]byte, 0)
)
if len(param) == 0 {
return "", nil
}
if res, err = Decrypt(param, []byte(aesKey)); err != nil {
return "", err
}
return string(res), nil
}
func (s *Service) doHash(plaintext string) []byte {
var res = make([]byte, 0)
if plaintext == "" {
return res
}
hash := md5.New()
hash.Write([]byte(plaintext))
hash.Write([]byte(md5slat))
res = hash.Sum(nil)
return res
}
// InetAtoN .
func InetAtoN(ip string) int64 {
ret := big.NewInt(0)
ret.SetBytes(net.ParseIP(ip).To4())
return ret.Int64()
}