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,21 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/job/main/passport-user-compare/cmd:all-srcs",
"//app/job/main/passport-user-compare/conf:all-srcs",
"//app/job/main/passport-user-compare/dao:all-srcs",
"//app/job/main/passport-user-compare/http:all-srcs",
"//app/job/main/passport-user-compare/model:all-srcs",
"//app/job/main/passport-user-compare/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,19 @@
# passport-user-compare
# Version 1.0.18
> fix ping panic
# Version 1.0.17
> double check
# Version 1.0.11
> add reg origin fixed
# Version 1.0.10
> fix insert action email verified
# Version 1.0.9
> fix email verified
# Version 1.0.0
> 项目初始化

View File

@@ -0,0 +1,12 @@
# Owner
wutao
wanghuan01
zhoujiahui
# Author
wutao
zhaoyiquan
chenjunxi
# Reviewer
wutao

View File

@@ -0,0 +1,18 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- chenjunxi
- wanghuan01
- wutao
- zhaoyiquan
- zhoujiahui
labels:
- job
- job/main/passport-user-compare
- main
options:
no_parent_owners: true
reviewers:
- chenjunxi
- wutao
- zhaoyiquan

View File

@@ -0,0 +1,21 @@
## passport-user-compare
### 项目简介
> 账号项目重构,用户基本信息数据对比脚本;
### 功能介绍
#### 1. 全量对比和修复
依赖于老库数据;每隔一天进行全量对比用户密码和盐、手机、邮箱、二次登录状态、密保问题等核心字段
#### 2. 增量对比和修复
1. 定时对比信息,并且依赖于老库进行修复(10分钟比对最近10分钟修改过的数据)
2. 当用户行为处罚需要要进行数据对比吗,并依赖于老库进行修复
#### 编译环境
> 请只用golang v1.8.x以上版本编译执行。
#### 依赖包
> 1.公共包go-common
#### 特别说明

View File

@@ -0,0 +1,42 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = ["passport-user-compare-job.toml"],
importpath = "go-common/app/job/main/passport-user-compare/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/passport-user-compare/conf:go_default_library",
"//app/job/main/passport-user-compare/http:go_default_library",
"//library/log:go_default_library",
"//library/net/trace: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"],
)

View File

@@ -0,0 +1,43 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"go-common/app/job/main/passport-user-compare/conf"
"go-common/app/job/main/passport-user-compare/http"
"go-common/library/log"
"go-common/library/net/trace"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() error(%v)", err)
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
// init trace
trace.Init(conf.Conf.Tracer)
defer trace.Close()
// service init
http.Init(conf.Conf)
// init signal
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("passport-user-compare get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
log.Info("passport-user-compare exit")
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,85 @@
[log]
dir = "/Users/allen/data/log/passport-user-compare"
dataFixSwitch = true
incrDataFixSwitch = true
[fullTask]
switch = true
step = 1000
accountEnd = 400002500
accountInfoEnd = 25053
accountSnsEnd = 25053
cronFullStr = "0 35 17 * * *"
[incTask]
switch = false
startTime = "2018-09-28 16:40:00"
stepDuration = "10m"
cronIncStr = "0 */10 * * * *"
[duplicateTask]
switch = false
duplicateCron = "*/30 * * * * ?"
[weChat]
token = "GYQeuDWBbAsCNeGz"
secret = "ZKpmgINTkianyMbMixyxcPQjMCSHCDrk"
username = "wutao"
[httpClient]
dial = "10s"
timeout = "10s"
keepAlive = "60s"
key = "4699a07e59d7149e"
secret = "test"
[httpClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.origin]
addr = "172.16.33.205:3306"
dsn = "aso:hA0DAnENNFz78kYB@tcp(172.16.33.205:3306)/aso?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
queryTimeout = "10s"
execTimeout = "20s"
tranTimeout = "20s"
[db.origin.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.user]
addr = "127.0.0.1:3306"
dsn = "root:123456@tcp(127.0.0.1:3306)/test?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
queryTimeout = "10s"
execTimeout = "20s"
tranTimeout = "20s"
[db.user.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.secret]
addr = "127.0.0.1:3306"
dsn = "root:123456@tcp(127.0.0.1:3306)/test?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
queryTimeout = "10s"
execTimeout = "20s"
tranTimeout = "20s"
[db.secret.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100

View File

@@ -0,0 +1,37 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/job/main/passport-user-compare/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/trace:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/BurntSushi/toml: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"],
)

View File

@@ -0,0 +1,139 @@
package conf
import (
"errors"
"flag"
"go-common/library/conf"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
httpx "go-common/library/net/http/blademaster"
"go-common/library/net/trace"
"go-common/library/time"
"github.com/BurntSushi/toml"
)
var (
confPath string
// Conf conf.
Conf = &Config{}
client *conf.Client
)
// Config config.
type Config struct {
// log
Log *log.Config
// Tracer tracer
Tracer *trace.Config
// DB db
DB *DB
// BM
BM *httpx.ServerConfig
// FullTask
FullTask *FullTask
// IncTask
IncTask *IncTask
// WeChat
WeChat *WeChat
// data fix switch
DataFixSwitch bool
IncrDataFixSwitch bool
// httpClient
HTTPClient *bm.ClientConfig
// DuplicateTask
DuplicateTask *DuplicateTask
FixEmailVerifiedSwitch bool
}
// FullTask full task compare
type FullTask struct {
Switch bool
Step int64
AccountEnd int64
AccountInfoEnd int64
AccountSnsEnd int64
CronFullStr string
}
// WeChat wechat basic info
type WeChat struct {
Token string
Secret string
Username string
}
// IncTask incr task compare
type IncTask struct {
Switch bool
StartTime string
StepDuration time.Duration
CronIncStr string
}
// DB db config.
type DB struct {
User *sql.Config
Origin *sql.Config
Secret *sql.Config
}
// DuplicateTask check duplicatet ask
type DuplicateTask struct {
Switch bool
DuplicateCron string
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init init config.
func Init() (err error) {
if confPath != "" {
return local()
}
return remote()
}
func local() (err error) {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
if err = load(); err != nil {
return
}
go func() {
for range client.Event() {
log.Info("config reload")
if load() != nil {
log.Error("config reload error (%v)", err)
}
}
}()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Toml2(); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config")
}
*Conf = *tmpConf
return
}

View File

@@ -0,0 +1,62 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"duplicate.go",
"origin.go",
"secret.go",
"user.go",
"wechat.go",
],
importpath = "go-common/app/job/main/passport-user-compare/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/passport-user-compare/conf:go_default_library",
"//app/job/main/passport-user-compare/model:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster: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 = [
"dao_test.go",
"duplicate_test.go",
"origin_test.go",
"secret_test.go",
"user_test.go",
"wechat_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/job/main/passport-user-compare/conf:go_default_library",
"//app/job/main/passport-user-compare/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,63 @@
package dao
import (
"context"
"go-common/app/job/main/passport-user-compare/conf"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
const (
safeQuestionSegment = 100
)
// Dao dao
type Dao struct {
c *conf.Config
httpClient *bm.Client
originDB *sql.DB
userDB *sql.DB
secretDB *sql.DB
}
// New new dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
originDB: sql.NewMySQL(c.DB.Origin),
userDB: sql.NewMySQL(c.DB.User),
secretDB: sql.NewMySQL(c.DB.Secret),
httpClient: bm.NewClient(c.HTTPClient),
}
return
}
// Ping check dao ok.
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.originDB.Ping(c); err != nil {
log.Info("dao.originDB.Ping() error(%v)", err)
}
if err = d.userDB.Ping(c); err != nil {
log.Info("dao.newDB.Ping() error(%v)", err)
}
if err = d.secretDB.Ping(c); err != nil {
log.Info("dao.secretDB.Ping() error(%v)", err)
}
return
}
// Close close connections.
func (d *Dao) Close() (err error) {
if d.originDB != nil {
d.originDB.Close()
}
if d.userDB != nil {
d.userDB.Close()
}
if d.secretDB != nil {
d.secretDB.Close()
}
return
}

View File

@@ -0,0 +1,34 @@
package dao
import (
"flag"
"go-common/app/job/main/passport-user-compare/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.passport.passport-user-compare-job")
flag.Set("conf_token", "5b735bbc35fa33c84fd2c89a54b6470c")
flag.Set("tree_id", "61394")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../cmd/passport-user-compare-job.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,77 @@
package dao
import (
"context"
"database/sql"
"go-common/app/job/main/passport-user-compare/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_getUserTelDuplicateSQL = "SELECT id,mid,tel,cid,tel_bind_time,status,ts FROM user_tel_duplicate WHERE status = 0 order by ts"
_getUserEmailDuplicateSQL = "SELECT id,mid,email,verified,email_bind_time,status,ts FROM user_email_duplicate WHERE status = 0 order by ts"
_updateTelDuplicateStatusSQL = "UPDATE user_tel_duplicate SET status = 1 WHERE id = ?"
_updateEmailDuplicateStatusSQL = "UPDATE user_email_duplicate SET status = 1 WHERE id = ?"
)
// UserTelDuplicate get user tel duplicate.
func (d *Dao) UserTelDuplicate(c context.Context) (res []*model.UserTelDuplicate, err error) {
var rows *xsql.Rows
if rows, err = d.userDB.Query(c, _getUserTelDuplicateSQL); err != nil {
log.Error("fail to get UserTelDuplicate, dao.userDB.Query(%s) error(%v)", _getUserTelDuplicateSQL, err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.UserTelDuplicate)
if err = rows.Scan(&r.ID, &r.Mid, &r.Tel, &r.Cid, &r.TelBindTime, &r.Status, &r.Timestamp); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
return
}
// UserEmailDuplicate get user email duplicate.
func (d *Dao) UserEmailDuplicate(c context.Context) (res []*model.UserEmailDuplicate, err error) {
var rows *xsql.Rows
if rows, err = d.userDB.Query(c, _getUserEmailDuplicateSQL); err != nil {
log.Error("fail to get UserEmailDuplicate, dao.userDB.Query(%s) error(%v)", _getUserEmailDuplicateSQL, err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.UserEmailDuplicate)
if err = rows.Scan(&r.ID, &r.Mid, &r.Email, &r.Verified, &r.EmailBindTime, &r.Status, &r.Timestamp); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
return
}
// UpdateUserTelDuplicateStatus update user tel duplicate status.
func (d *Dao) UpdateUserTelDuplicateStatus(c context.Context, id int64) (affected int64, err error) {
var res sql.Result
if res, err = d.userDB.Exec(c, _updateTelDuplicateStatusSQL, id); err != nil {
log.Error("fail to update tel duplicate status, id(%d) dao.userDB.Exec() error(%+v)", id, err)
return
}
return res.RowsAffected()
}
// UpdateUserEmailDuplicateStatus update user email duplicate status.
func (d *Dao) UpdateUserEmailDuplicateStatus(c context.Context, id int64) (affected int64, err error) {
var res sql.Result
if res, err = d.userDB.Exec(c, _updateEmailDuplicateStatusSQL, id); err != nil {
log.Error("fail to update email duplicate status, id(%d) dao.userDB.Exec() error(%+v)", id, err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,70 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoUserTelDuplicate(t *testing.T) {
convey.Convey("UserTelDuplicate", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.UserTelDuplicate(c)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoUserEmailDuplicate(t *testing.T) {
convey.Convey("UserEmailDuplicate", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.UserEmailDuplicate(c)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoUpdateUserTelDuplicateStatus(t *testing.T) {
convey.Convey("UpdateUserTelDuplicateStatus", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.UpdateUserTelDuplicateStatus(c, id)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpdateUserEmailDuplicateStatus(t *testing.T) {
convey.Convey("UpdateUserEmailDuplicateStatus", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.UpdateUserEmailDuplicateStatus(c, id)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,291 @@
package dao
import (
"context"
"fmt"
"time"
"go-common/app/job/main/passport-user-compare/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
var (
selectAccountSQL = "SELECT mid, userid, uname, pwd, salt, email, tel, mobile_verified, isleak, country_id, modify_time FROM aso_account WHERE mid > ? limit ? "
selectAccountByMidSQL = "SELECT mid, userid, uname, pwd, salt, email, tel, mobile_verified, isleak, country_id, modify_time FROM aso_account WHERE mid = ?"
selectAccountByTelSQL = "SELECT mid, userid, uname, pwd, salt, email, tel, mobile_verified, isleak, country_id, modify_time FROM aso_account WHERE tel = ?"
selectAccountByMailSQL = "SELECT mid, userid, uname, pwd, salt, email, tel, mobile_verified, isleak, country_id, modify_time FROM aso_account WHERE email = ?"
selectAccountByTimeSQL = "SELECT mid, userid, uname, pwd, salt, email, tel, mobile_verified, isleak, country_id, modify_time FROM aso_account WHERE modify_time >= ? AND modify_time < ?"
selectAccountInfoSQL = "SELECT id, mid, spacesta, safe_question, safe_answer, join_time, join_ip, active_time, modify_time FROM aso_account_info%d WHERE id > ? limit ?"
selectAccountInfoByMidSQL = "SELECT id, mid, spacesta, safe_question, safe_answer, join_time, join_ip, active_time, modify_time FROM aso_account_info%d WHERE mid = ? "
selectAccountInfoByTimeSQL = "SELECT id, mid, spacesta, safe_question, safe_answer, join_time, join_ip, active_time, modify_time FROM aso_account_info%d WHERE modify_time >= ? AND modify_time < ? "
selectAccountSnsSQL = "SELECT mid, sina_uid, sina_access_token, sina_access_expires, qq_openid, qq_access_token, qq_access_expires FROM aso_account_sns WHERE mid > ? limit ?"
selectAccountSnsByMidSQL = "SELECT mid, sina_uid, sina_access_token, sina_access_expires, qq_openid, qq_access_token, qq_access_expires FROM aso_account_sns WHERE mid = ? "
selectOriginTelBindLogSQL = "SELECT timestamp FROM aso_telephone_bind_log WHERE mid = ? order by timestamp limit 1"
selectAccountRegByMidSQL = "SELECT id, mid, origintype, regtype, appid, ctime, mtime FROM aso_account_reg_origin_%d WHERE mid = ? "
selectAccountRegByTimeSQL = "SELECT id, mid, origintype, regtype, appid, ctime, mtime FROM aso_account_reg_origin_%d WHERE mtime >= ? AND mtime < ? "
)
// BatchQueryAccount batch query account
func (d *Dao) BatchQueryAccount(c context.Context, start, limit int64) (res []*model.OriginAccount, err error) {
var rows *xsql.Rows
if rows, err = d.originDB.Query(c, selectAccountSQL, start, limit); err != nil {
log.Error("fail to get BatchQueryAccount, dao.originDB.Query(%s) error(%v)", selectAccountSQL, err)
return
}
defer rows.Close()
for rows.Next() {
var telPtr, emailPtr *string
r := new(model.OriginAccount)
if err = rows.Scan(&r.Mid, &r.UserID, &r.Uname, &r.Pwd, &r.Salt, &emailPtr, &telPtr, &r.MobileVerified, &r.Isleak, &r.CountryID, &r.MTime); err != nil {
log.Error("BatchQueryAccount row.Scan() error(%v)", err)
res = nil
return
}
if telPtr != nil {
r.Tel = *telPtr
}
if emailPtr != nil {
r.Email = *emailPtr
}
res = append(res, r)
}
return
}
// QueryAccountByMid query account by mid
func (d *Dao) QueryAccountByMid(c context.Context, mid int64) (res *model.OriginAccount, err error) {
row := d.originDB.QueryRow(c, selectAccountByMidSQL, mid)
res = new(model.OriginAccount)
var telPtr, emailPtr *string
if err = row.Scan(&res.Mid, &res.UserID, &res.Uname, &res.Pwd, &res.Salt, &emailPtr, &telPtr, &res.MobileVerified, &res.Isleak, &res.CountryID, &res.MTime); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("QueryAccountByMid row.Scan() error(%v)", err)
}
return
}
if telPtr != nil {
res.Tel = *telPtr
}
if emailPtr != nil {
res.Email = *emailPtr
}
return
}
// QueryAccountByTel query account by mid
func (d *Dao) QueryAccountByTel(c context.Context, tel string) (res *model.OriginAccount, err error) {
row := d.originDB.QueryRow(c, selectAccountByTelSQL, tel)
res = new(model.OriginAccount)
var telPtr, emailPtr *string
if err = row.Scan(&res.Mid, &res.UserID, &res.Uname, &res.Pwd, &res.Salt, &emailPtr, &telPtr, &res.MobileVerified, &res.Isleak, &res.CountryID, &res.MTime); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("QueryAccountByTel row.Scan() error(%v)", err)
}
return
}
if telPtr != nil {
res.Tel = *telPtr
}
if emailPtr != nil {
res.Email = *emailPtr
}
return
}
// QueryAccountByMail query account by mid
func (d *Dao) QueryAccountByMail(c context.Context, mail string) (res *model.OriginAccount, err error) {
row := d.originDB.QueryRow(c, selectAccountByMailSQL, mail)
res = new(model.OriginAccount)
var telPtr, emailPtr *string
if err = row.Scan(&res.Mid, &res.UserID, &res.Uname, &res.Pwd, &res.Salt, &emailPtr, &telPtr, &res.MobileVerified, &res.Isleak, &res.CountryID, &res.MTime); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("QueryAccountByMail row.Scan() error(%v)", err)
}
return
}
if telPtr != nil {
res.Tel = *telPtr
}
if emailPtr != nil {
res.Email = *emailPtr
}
return
}
// BatchQueryAccountByTime batch query by time
func (d *Dao) BatchQueryAccountByTime(c context.Context, start, end time.Time) (res []*model.OriginAccount, err error) {
var rows *xsql.Rows
if rows, err = d.originDB.Query(c, selectAccountByTimeSQL, start, end); err != nil {
log.Error("fail to get BatchQueryAccountByTime, dao.originDB.Query(%s) error(%v)", selectAccountSQL, err)
return
}
defer rows.Close()
for rows.Next() {
var telPtr, emailPtr *string
r := new(model.OriginAccount)
if err = rows.Scan(&r.Mid, &r.UserID, &r.Uname, &r.Pwd, &r.Salt, &emailPtr, &telPtr, &r.MobileVerified, &r.Isleak, &r.CountryID, &r.MTime); err != nil {
log.Error("BatchQueryAccountByTime row.Scan() error(%v)", err)
res = nil
return
}
if telPtr != nil {
r.Tel = *telPtr
}
if emailPtr != nil {
r.Email = *emailPtr
}
res = append(res, r)
}
return
}
// BatchQueryAccountInfo batch query account info
func (d *Dao) BatchQueryAccountInfo(c context.Context, start, limit int64, suffix int) (res []*model.OriginAccountInfo, err error) {
var rows *xsql.Rows
if rows, err = d.originDB.Query(c, fmt.Sprintf(selectAccountInfoSQL, suffix), start, limit); err != nil {
log.Error("fail to get BatchQueryAccountInfo, dao.originDB.Query(%s) error(%v)", selectAccountInfoSQL, err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.OriginAccountInfo)
if err = rows.Scan(&r.ID, &r.Mid, &r.Spacesta, &r.SafeQuestion, &r.SafeAnswer, &r.JoinTime, &r.JoinIP, &r.ActiveTime, &r.MTime); err != nil {
log.Error("BatchQueryAccountInfo row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
return
}
// QueryAccountInfoByMid query account info by mid
func (d *Dao) QueryAccountInfoByMid(c context.Context, mid int64) (res *model.OriginAccountInfo, err error) {
row := d.originDB.QueryRow(c, fmt.Sprintf(selectAccountInfoByMidSQL, mid%30), mid)
res = new(model.OriginAccountInfo)
if err = row.Scan(&res.ID, &res.Mid, &res.Spacesta, &res.SafeQuestion, &res.SafeAnswer, &res.JoinTime, &res.JoinIP, &res.ActiveTime, &res.MTime); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("QueryAccountInfoByMid row.Scan() error(%v)", err)
}
return
}
return
}
// BatchQueryAccountInfoByTime batch query account info
func (d *Dao) BatchQueryAccountInfoByTime(c context.Context, start, end time.Time, suffix int) (res []*model.OriginAccountInfo, err error) {
var rows *xsql.Rows
if rows, err = d.originDB.Query(c, fmt.Sprintf(selectAccountInfoByTimeSQL, suffix), start, end); err != nil {
log.Error("fail to get BatchQueryAccountInfoByTime, dao.originDB.Query(%s) error(%v)", selectAccountInfoSQL, err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.OriginAccountInfo)
if err = rows.Scan(&r.ID, &r.Mid, &r.Spacesta, &r.SafeQuestion, &r.SafeAnswer, &r.JoinTime, &r.JoinIP, &r.ActiveTime, &r.MTime); err != nil {
log.Error("BatchQueryAccountInfoByTime row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
return
}
// BatchQueryAccountSns batch query account sns
func (d *Dao) BatchQueryAccountSns(c context.Context, start, limit int64) (res []*model.OriginAccountSns, err error) {
var rows *xsql.Rows
if rows, err = d.originDB.Query(c, selectAccountSnsSQL, start, limit); err != nil {
log.Error("fail to get BatchQueryAccountSns, dao.originDB.Query(%s) error(%v)", selectAccountSnsSQL, err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.OriginAccountSns)
if err = rows.Scan(&r.Mid, &r.SinaUID, &r.SinaAccessToken, &r.SinaAccessExpires, &r.QQOpenid, &r.QQAccessToken, &r.QQAccessExpires); err != nil {
log.Error("BatchQueryAccountSns row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
return
}
// QueryAccountSnsByMid query account sns by mid
func (d *Dao) QueryAccountSnsByMid(c context.Context, mid int64) (res *model.OriginAccountSns, err error) {
row := d.originDB.QueryRow(c, selectAccountSnsByMidSQL, mid)
res = new(model.OriginAccountSns)
if err = row.Scan(&res.Mid, &res.SinaUID, &res.SinaAccessToken, &res.SinaAccessExpires, &res.QQOpenid, &res.QQAccessToken, &res.QQAccessExpires); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("QueryAccountSnsByMid row.Scan() error(%v)", err)
}
return
}
return
}
// QueryTelBindLog get aso tel bind log.
func (d *Dao) QueryTelBindLog(c context.Context, mid int64) (res int64, err error) {
if err = d.originDB.QueryRow(c, selectOriginTelBindLogSQL, mid).Scan(&res); err != nil {
if err == xsql.ErrNoRows {
err = nil
} else {
log.Error("fail to get AsoTelBindLog, dao.originDB.QueryRow(%s) error(%v)", selectOriginTelBindLogSQL, err)
}
return
}
return
}
// QueryAccountRegByMid query account reg by mid
func (d *Dao) QueryAccountRegByMid(c context.Context, mid int64) (res *model.OriginAccountReg, err error) {
row := d.originDB.QueryRow(c, fmt.Sprintf(selectAccountRegByMidSQL, mid%20), mid)
res = new(model.OriginAccountReg)
if err = row.Scan(&res.ID, &res.Mid, &res.OriginType, &res.RegType, &res.AppID, &res.CTime, &res.MTime); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("QueryAccountRegByMid row.Scan() error(%v)", err)
}
return
}
return
}
// BatchQueryAccountRegByTime batch query account info
func (d *Dao) BatchQueryAccountRegByTime(c context.Context, start, end time.Time, suffix int) (res []*model.OriginAccountReg, err error) {
var rows *xsql.Rows
if rows, err = d.originDB.Query(c, fmt.Sprintf(selectAccountRegByTimeSQL, suffix), start, end); err != nil {
log.Error("fail to get BatchQueryAccountRegByTime, dao.originDB.Query(%s) error(%v)", selectAccountInfoSQL, err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.OriginAccountReg)
if err = rows.Scan(&r.ID, &r.Mid, &r.OriginType, &r.RegType, &r.AppID, &r.CTime, &r.MTime); err != nil {
log.Error("BatchQueryAccountInfoByTime row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
return
}

View File

@@ -0,0 +1,226 @@
package dao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoBatchQueryAccount(t *testing.T) {
convey.Convey("BatchQueryAccount", t, func(ctx convey.C) {
var (
c = context.Background()
start = int64(0)
limit = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.BatchQueryAccount(c, start, limit)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoQueryAccountByMid(t *testing.T) {
convey.Convey("QueryAccountByMid", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryAccountByMid(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoQueryAccountByTel(t *testing.T) {
convey.Convey("QueryAccountByTel", t, func(ctx convey.C) {
var (
c = context.Background()
tel = "13122111111"
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryAccountByTel(c, tel)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoQueryAccountByMail(t *testing.T) {
convey.Convey("QueryAccountByMail", t, func(ctx convey.C) {
var (
c = context.Background()
mail = "598717394@qq.com"
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryAccountByMail(c, mail)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoBatchQueryAccountByTime(t *testing.T) {
convey.Convey("BatchQueryAccountByTime", t, func(ctx convey.C) {
var (
c = context.Background()
start = time.Now()
end = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.BatchQueryAccountByTime(c, start, end)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoBatchQueryAccountInfo(t *testing.T) {
convey.Convey("BatchQueryAccountInfo", t, func(ctx convey.C) {
var (
c = context.Background()
start = int64(0)
limit = int64(0)
suffix = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.BatchQueryAccountInfo(c, start, limit, suffix)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoQueryAccountInfoByMid(t *testing.T) {
convey.Convey("QueryAccountInfoByMid", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(2)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryAccountInfoByMid(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoBatchQueryAccountInfoByTime(t *testing.T) {
convey.Convey("BatchQueryAccountInfoByTime", t, func(ctx convey.C) {
var (
c = context.Background()
start = time.Now()
end = time.Now()
suffix = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.BatchQueryAccountInfoByTime(c, start, end, suffix)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoBatchQueryAccountSns(t *testing.T) {
convey.Convey("BatchQueryAccountSns", t, func(ctx convey.C) {
var (
c = context.Background()
start = int64(0)
limit = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.BatchQueryAccountSns(c, start, limit)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoQueryAccountSnsByMid(t *testing.T) {
convey.Convey("QueryAccountSnsByMid", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(2)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryAccountSnsByMid(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryTelBindLog(t *testing.T) {
convey.Convey("QueryTelBindLog", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(2)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryTelBindLog(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryAccountRegByMid(t *testing.T) {
convey.Convey("QueryAccountRegByMid", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(22222222)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryAccountRegByMid(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoBatchQueryAccountRegByTime(t *testing.T) {
convey.Convey("BatchQueryAccountRegByTime", t, func(ctx convey.C) {
var (
c = context.Background()
start = time.Now()
end = time.Now()
suffix = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.BatchQueryAccountRegByTime(c, start, end, suffix)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,33 @@
package dao
import (
"context"
"go-common/app/job/main/passport-user-compare/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
var (
secretSQL = "SELECT us.key_type, us.key FROM user_secret us"
)
// LoadSecret load secret
func (d *Dao) LoadSecret(c context.Context) (res []*model.Secret, err error) {
var rows *xsql.Rows
if rows, err = d.secretDB.Query(c, secretSQL); err != nil {
log.Error("fail to get secretSQL, dao.secretDB.Query(%s) error(%v)", secretSQL, err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.Secret)
if err = rows.Scan(&r.KeyType, &r.Key); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
return
}

View File

@@ -0,0 +1,23 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoLoadSecret(t *testing.T) {
convey.Convey("LoadSecret", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.LoadSecret(c)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,352 @@
package dao
import (
"context"
"database/sql"
"fmt"
"go-common/app/job/main/passport-user-compare/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
var (
insertUserBaseSQL = "INSERT INTO user_base (mid,userid,pwd,salt,status,deleted,mtime) VALUES(?,?,?,?,?,?,?)"
selectUserBaseSQL = "SELECT mid, userid, pwd, salt, status FROM user_base WHERE mid = ?"
updateUserBaseSQL = "UPDATE user_base SET userid = ?, pwd = ? ,salt = ? ,status = ? WHERE mid = ?"
insertUserTelSQL = "INSERT INTO user_tel (mid,tel,cid,tel_bind_time,mtime) VALUES(?,?,?,?,?)"
selectUserTelSQL = "SELECT mid, tel, cid, tel_bind_time FROM user_tel WHERE mid = ?"
updateUserTelSQL = "UPDATE user_tel SET tel = ? ,cid = ? WHERE mid = ?"
insertUserMailSQL = "INSERT INTO user_email (mid,email,verified,email_bind_time,mtime) VALUES(?,?,?,?,?)"
selectUserMailSQL = "SELECT mid,email,email_bind_time FROM user_email WHERE mid = ?"
updateUserMailSQL = "UPDATE user_email SET email = ? WHERE mid = ?"
updateUserMailVerifiedSQL = "UPDATE user_email SET verified = ? WHERE mid = ?"
insertUserSafeQuestionSQL = "INSERT INTO user_safe_question%02d (mid,safe_question,safe_answer,safe_bind_time) VALUES(?,?,?,?)"
selectUserSafeQuestionSQL = "SELECT mid, safe_question, safe_answer FROM user_safe_question%02d WHERE mid = ?"
updateUserSafeQuestionSQL = "UPDATE user_safe_question%02d SET safe_question = ? ,safe_answer = ? WHERE mid = ? "
insertThirdBindSQL = "INSERT INTO user_third_bind (mid,openid,platform,token,expires) VALUES(?,?,?,?,?)"
selectThirdBindSQL = "SELECT mid, openid, platform, token FROM user_third_bind WHERE mid = ? AND platform = ?"
updateThirdBindSQL = "UPDATE user_third_bind SET openid = ? ,token = ? WHERE mid = ? AND platform = ? "
queryCountryCodeSQL = "SELECT id,code FROM country_code"
queryMidByTelSQL = "SELECT mid FROM user_tel WHERE tel = ? and cid = ?"
queryMidByEmailSQL = "SELECT mid FROM user_email WHERE email = ?"
getUnverifiedEmail = "SELECT mid FROM user_email where mid > ? and verified = 0 limit 20000"
_getUserRegOriginByMidSQL = "SELECT mid,join_ip,join_time,origin,reg_type,appid from user_reg_origin%02d where mid = ?"
_insertUpdateUserRegOriginTypeSQL = "INSERT INTO user_reg_origin%02d (mid,join_ip,join_time,origin,reg_type,appid,ctime,mtime) VALUES (?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE join_ip=?,join_time=?,origin=?,reg_type=?,appid=?,ctime=?,mtime=?"
)
// QueryUserBase query user basic info by mid
func (d *Dao) QueryUserBase(c context.Context, mid int64) (res *model.UserBase, err error) {
row := d.userDB.QueryRow(c, selectUserBaseSQL, mid)
res = new(model.UserBase)
if err = row.Scan(&res.Mid, &res.UserID, &res.Pwd, &res.Salt, &res.Status); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
return
}
return
}
// UpdateUserBase update user base
func (d *Dao) UpdateUserBase(c context.Context, a *model.UserBase) (affected int64, err error) {
var res sql.Result
if res, err = d.userDB.Exec(c, updateUserBaseSQL, a.UserID, a.Pwd, a.Salt, a.Status, a.Mid); err != nil {
log.Error("failed to update user base, dao.userDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// InsertUserBase add user base.
func (d *Dao) InsertUserBase(c context.Context, a *model.UserBase) (affected int64, err error) {
var res sql.Result
if res, err = d.userDB.Exec(c, insertUserBaseSQL, a.Mid, a.UserID, a.Pwd, a.Salt, a.Status, a.Deleted, a.MTime); err != nil {
log.Error("fail to add user base, userBase(%+v) dao.userDB.Exec() error(%+v)", a, err)
return
}
return res.RowsAffected()
}
// QueryUserTel query user tel info by mid
func (d *Dao) QueryUserTel(c context.Context, mid int64) (res *model.UserTel, err error) {
row := d.userDB.QueryRow(c, selectUserTelSQL, mid)
res = new(model.UserTel)
var cidPtr *string
if err = row.Scan(&res.Mid, &res.Tel, &cidPtr, &res.TelBindTime); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
return
}
if cidPtr != nil {
res.Cid = *cidPtr
}
return
}
// UpdateUserTel update user tel
func (d *Dao) UpdateUserTel(c context.Context, a *model.UserTel) (affected int64, err error) {
var (
res sql.Result
telPtr *[]byte
cidPtr string
)
if len(a.Tel) != 0 {
telPtr = &a.Tel
cidPtr = a.Cid
}
if res, err = d.userDB.Exec(c, updateUserTelSQL, telPtr, cidPtr, a.Mid); err != nil {
log.Error("failed to update user tel, dao.userDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// InsertUserTel insert user tel
func (d *Dao) InsertUserTel(c context.Context, a *model.UserTel) (affected int64, err error) {
var (
res sql.Result
telPtr *[]byte
cidPtr string
)
if len(a.Tel) != 0 {
telPtr = &a.Tel
cidPtr = a.Cid
}
if res, err = d.userDB.Exec(c, insertUserTelSQL, a.Mid, telPtr, cidPtr, a.TelBindTime, a.MTime); err != nil {
log.Error("fail to add user tel, userTel(%+v) dao.userDB.Exec() error(%+v)", a, err)
return
}
return res.RowsAffected()
}
// QueryUserMail query user mail info by mid
func (d *Dao) QueryUserMail(c context.Context, mid int64) (res *model.UserEmail, err error) {
row := d.userDB.QueryRow(c, selectUserMailSQL, mid)
res = new(model.UserEmail)
if err = row.Scan(&res.Mid, &res.Email, &res.EmailBindTime); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
return
}
return
}
// UpdateUserMail update user tel
func (d *Dao) UpdateUserMail(c context.Context, a *model.UserEmail) (affected int64, err error) {
var res sql.Result
if res, err = d.userDB.Exec(c, updateUserMailSQL, a.Email, a.Mid); err != nil {
log.Error("failed to update user mail, dao.userDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// UpdateUserMailVerified update user email verified
func (d *Dao) UpdateUserMailVerified(c context.Context, a *model.UserEmail) (affected int64, err error) {
var res sql.Result
if res, err = d.userDB.Exec(c, updateUserMailVerifiedSQL, a.Verified, a.Mid); err != nil {
log.Error("failed to update user mail verified, dao.userDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// InsertUserEmail add user email.
func (d *Dao) InsertUserEmail(c context.Context, a *model.UserEmail) (affected int64, err error) {
var (
res sql.Result
emailPtr *[]byte
)
if len(a.Email) != 0 {
emailPtr = &a.Email
}
if res, err = d.userDB.Exec(c, insertUserMailSQL, a.Mid, emailPtr, a.Verified, a.EmailBindTime, a.MTime); err != nil {
log.Error("fail to add user email, userEmail(%+v) dao.userDB.Exec() error(%+v)", a, err)
return
}
return res.RowsAffected()
}
// QueryUserSafeQuestion query user safe question by mid
func (d *Dao) QueryUserSafeQuestion(c context.Context, mid int64) (res *model.UserSafeQuestion, err error) {
row := d.userDB.QueryRow(c, fmt.Sprintf(selectUserSafeQuestionSQL, mid%safeQuestionSegment), mid)
res = new(model.UserSafeQuestion)
if err = row.Scan(&res.Mid, &res.SafeQuestion, &res.SafeAnswer); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
return
}
return
}
// UpdateUserSafeQuestion update user tel
func (d *Dao) UpdateUserSafeQuestion(c context.Context, a *model.UserSafeQuestion) (affected int64, err error) {
var res sql.Result
if res, err = d.userDB.Exec(c, fmt.Sprintf(updateUserSafeQuestionSQL, a.Mid%safeQuestionSegment), a.SafeQuestion, a.SafeAnswer, a.Mid); err != nil {
log.Error("failed to update user safe question, dao.userDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// InsertUserSafeQuestion insert user safe question
func (d *Dao) InsertUserSafeQuestion(c context.Context, a *model.UserSafeQuestion) (affected int64, err error) {
var res sql.Result
if res, err = d.userDB.Exec(c, fmt.Sprintf(insertUserSafeQuestionSQL, a.Mid%safeQuestionSegment), a.Mid, a.SafeQuestion, a.SafeAnswer, a.SafeBindTime); err != nil {
log.Error("fail to add user safe question, userSafeQuestion(%+v) dao.userDB.Exec() error(%+v)", a, err)
return
}
return res.RowsAffected()
}
// QueryUserThirdBind query user third bind by mid and platform
func (d *Dao) QueryUserThirdBind(c context.Context, mid, platform int64) (res *model.UserThirdBind, err error) {
row := d.userDB.QueryRow(c, selectThirdBindSQL, mid, platform)
res = new(model.UserThirdBind)
if err = row.Scan(&res.Mid, &res.OpenID, &res.PlatForm, &res.Token); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
return
}
return
}
// UpdateUserThirdBind update user third bind
func (d *Dao) UpdateUserThirdBind(c context.Context, a *model.UserThirdBind) (affected int64, err error) {
var res sql.Result
if res, err = d.userDB.Exec(c, updateThirdBindSQL, a.OpenID, a.Token, a.Mid, a.PlatForm); err != nil {
log.Error("failed to update user third bind sql, dao.userDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// InsertUserThirdBind insert user third bind.
func (d *Dao) InsertUserThirdBind(c context.Context, a *model.UserThirdBind) (affected int64, err error) {
var res sql.Result
if res, err = d.userDB.Exec(c, insertThirdBindSQL, a.Mid, a.OpenID, a.PlatForm, a.Token, a.Expires); err != nil {
log.Error("fail to add user third bind, userThirdBind(%+v) dao.userDB.Exec() error(%+v)", a, err)
return
}
return res.RowsAffected()
}
// QueryCountryCode query country code
func (d *Dao) QueryCountryCode(c context.Context) (res map[int64]string, err error) {
var rows *xsql.Rows
if rows, err = d.userDB.Query(c, queryCountryCodeSQL); err != nil {
log.Error("fail to get CountryCodeMap, dao.originDB.Query(%s) error(%v)", queryCountryCodeSQL, err)
return
}
defer rows.Close()
res = make(map[int64]string)
for rows.Next() {
var (
id int64
code string
)
if err = rows.Scan(&id, &code); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res[id] = code
}
return
}
// GetMidByTel get mid by tel.
func (d *Dao) GetMidByTel(c context.Context, a *model.UserTel) (mid int64, err error) {
if err = d.userDB.QueryRow(c, queryMidByTelSQL, a.Tel, a.Cid).Scan(&mid); err != nil {
log.Error("fail to get mid by tel, dao.userDB.QueryRow(%s) error(%+v)", queryMidByTelSQL, err)
return
}
return
}
// GetMidByEmail get mid by email.
func (d *Dao) GetMidByEmail(c context.Context, a *model.UserEmail) (mid int64, err error) {
if err = d.userDB.QueryRow(c, queryMidByEmailSQL, a.Email).Scan(&mid); err != nil {
log.Error("fail to get mid by email, dao.userDB.QueryRow(%s) error(%+v)", queryMidByEmailSQL, err)
return
}
return
}
// GetUnverifiedEmail get unverified email.
func (d *Dao) GetUnverifiedEmail(c context.Context, start int64) (res []*model.UserEmail, err error) {
var rows *xsql.Rows
if rows, err = d.userDB.Query(c, getUnverifiedEmail, start); err != nil {
log.Error("fail to get UnverifiedEmail, dao.userDB.Query(%s) error(%v)", getUnverifiedEmail, err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.UserEmail)
if err = rows.Scan(&r.Mid); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
return
}
// GetUserRegOriginByMid get user reg origin by mid.
func (d *Dao) GetUserRegOriginByMid(c context.Context, mid int64) (res *model.UserRegOrigin, err error) {
res = &model.UserRegOrigin{}
if err = d.userDB.QueryRow(c, fmt.Sprintf(_getUserRegOriginByMidSQL, tableIndex(mid)), mid).Scan(&res.Mid, &res.JoinIP, &res.JoinTime, &res.Origin, &res.RegType, &res.AppID); err != nil {
if err == xsql.ErrNoRows {
err = nil
res = nil
} else {
log.Error("fail to get UserRegOrigin by mid(%d), dao.userDB.QueryRow(%s) error(%+v)", mid, _getUserRegOriginByMidSQL, err)
}
return
}
return
}
// InsertUpdateUserRegOriginType insert update user reg origin type.
func (d *Dao) InsertUpdateUserRegOriginType(c context.Context, a *model.UserRegOrigin) (affected int64, err error) {
var res sql.Result
if res, err = d.userDB.Exec(c, fmt.Sprintf(_insertUpdateUserRegOriginTypeSQL, tableIndex(a.Mid)), a.Mid, a.JoinIP, a.JoinTime, a.Origin, a.RegType, a.AppID, a.CTime, a.MTime,
a.JoinIP, a.JoinTime, a.Origin, a.RegType, a.AppID, a.CTime, a.MTime); err != nil {
log.Error("fail to insert update user reg origin type, userRegOrigin(%+v) dao.userDB.Exec() error(%+v)", a, err)
return
}
return res.RowsAffected()
}
func tableIndex(mid int64) int64 {
return mid % 100
}

View File

@@ -0,0 +1,411 @@
package dao
import (
"context"
"testing"
"go-common/app/job/main/passport-user-compare/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoQueryUserBase(t *testing.T) {
convey.Convey("QueryUserBase", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryUserBase(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpdateUserBase(t *testing.T) {
convey.Convey("UpdateUserBase", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserBase{
Mid: 1111111,
UserID: "test_0000_0001",
Pwd: []byte{},
Salt: "",
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.UpdateUserBase(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoInsertUserBase(t *testing.T) {
convey.Convey("InsertUserBase", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserBase{
Mid: 1111111111,
UserID: "test_0000_0002",
Pwd: []byte{},
Salt: "",
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.InsertUserBase(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryUserTel(t *testing.T) {
convey.Convey("QueryUserTel", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1111111111)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryUserTel(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpdateUserTel(t *testing.T) {
convey.Convey("UpdateUserTel", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserTel{
Mid: 1111111111,
Tel: []byte{},
Cid: "",
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.UpdateUserTel(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoInsertUserTel(t *testing.T) {
convey.Convey("InsertUserTel", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserTel{
Mid: 1111111111,
Tel: []byte{},
Cid: "",
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.InsertUserTel(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryUserMail(t *testing.T) {
convey.Convey("QueryUserMail", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1111111111)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryUserMail(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpdateUserMail(t *testing.T) {
convey.Convey("UpdateUserMail", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserEmail{
Mid: 1111111111,
Email: []byte{},
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.UpdateUserMail(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpdateUserMailVerified(t *testing.T) {
convey.Convey("UpdateUserMailVerified", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserEmail{
Mid: 1111111111,
Email: []byte{},
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.UpdateUserMailVerified(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoInsertUserEmail(t *testing.T) {
convey.Convey("InsertUserEmail", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserEmail{
Mid: 1111111111,
Email: []byte{},
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.InsertUserEmail(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryUserSafeQuestion(t *testing.T) {
convey.Convey("QueryUserSafeQuestion", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1111111111)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryUserSafeQuestion(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoUpdateUserSafeQuestion(t *testing.T) {
convey.Convey("UpdateUserSafeQuestion", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserSafeQuestion{
Mid: 1111111111,
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.UpdateUserSafeQuestion(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoInsertUserSafeQuestion(t *testing.T) {
convey.Convey("InsertUserSafeQuestion", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserSafeQuestion{
Mid: 1111111111,
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.InsertUserSafeQuestion(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryUserThirdBind(t *testing.T) {
convey.Convey("QueryUserThirdBind", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1111111111)
platform = int64(1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryUserThirdBind(c, mid, platform)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDaoUpdateUserThirdBind(t *testing.T) {
convey.Convey("UpdateUserThirdBind", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserThirdBind{
Mid: 1111111111,
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.UpdateUserThirdBind(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoInsertUserThirdBind(t *testing.T) {
convey.Convey("InsertUserThirdBind", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserThirdBind{
Mid: 1111111111,
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.InsertUserThirdBind(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryCountryCode(t *testing.T) {
convey.Convey("QueryCountryCode", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.QueryCountryCode(c)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoGetMidByTel(t *testing.T) {
convey.Convey("GetMidByTel", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserTel{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
mid, err := d.GetMidByTel(c, a)
ctx.Convey("Then err should be nil.mid should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(mid, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoGetMidByEmail(t *testing.T) {
convey.Convey("GetMidByEmail", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserEmail{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
mid, err := d.GetMidByEmail(c, a)
ctx.Convey("Then err should be nil.mid should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(mid, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoGetUnverifiedEmail(t *testing.T) {
convey.Convey("GetUnverifiedEmail", t, func(ctx convey.C) {
var (
c = context.Background()
start = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetUnverifiedEmail(c, start)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoGetUserRegOriginByMid(t *testing.T) {
convey.Convey("GetUserRegOriginByMid", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetUserRegOriginByMid(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoInsertUpdateUserRegOriginType(t *testing.T) {
convey.Convey("InsertUpdateUserRegOriginType", t, func(ctx convey.C) {
var (
c = context.Background()
a = &model.UserRegOrigin{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
affected, err := d.InsertUpdateUserRegOriginType(c, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDaotableIndex(t *testing.T) {
convey.Convey("tableIndex", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := tableIndex(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,84 @@
package dao
import (
"bytes"
"context"
"crypto/md5"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"sort"
"strconv"
"time"
"go-common/library/log"
)
type wechatResp struct {
Status int `json:"status"`
Msg string `json:"msg"`
}
const (
_url = "http://bap.bilibili.co/api/v1/message/add"
)
// SendWechat send stat to wechat
func (d *Dao) SendWechat(param map[string]int64) (err error) {
var stat []byte
if stat, err = json.Marshal(param); err != nil {
log.Error("json.Marshal error ,error is (%+v)", err)
return
}
params := map[string]string{
"content": string(stat),
"timestamp": strconv.FormatInt(time.Now().Unix(), 10),
"token": d.c.WeChat.Token,
"type": "wechat",
"username": d.c.WeChat.Username,
"url": "",
}
params["signature"] = d.sign(params)
b, err := json.Marshal(params)
if err != nil {
log.Error("SendWechat json.Marshal error(%v)", err)
return
}
req, err := http.NewRequest(http.MethodPost, _url, bytes.NewReader(b))
if err != nil {
log.Error("SendWechat NewRequest error(%v), params(%s)", err, string(b))
return
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
res := wechatResp{}
if err = d.httpClient.Do(context.TODO(), req, &res); err != nil {
log.Error("SendWechat Do error(%v), params(%s)", err, string(b))
return
}
if res.Status != 0 {
err = fmt.Errorf("status(%d) msg(%s)", res.Status, res.Msg)
log.Error("SendWechat response error(%v), params(%s)", err, string(b))
}
return
}
func (d *Dao) sign(params map[string]string) string {
var keys []string
for k := range params {
keys = append(keys, k)
}
sort.Strings(keys)
buf := bytes.Buffer{}
for _, k := range keys {
if buf.Len() > 0 {
buf.WriteByte('&')
}
buf.WriteString(url.QueryEscape(k) + "=")
buf.WriteString(url.QueryEscape(params[k]))
}
h := md5.New()
io.WriteString(h, buf.String()+d.c.WeChat.Secret)
return fmt.Sprintf("%x", h.Sum(nil))
}

View File

@@ -0,0 +1,35 @@
package dao
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoSendWechat(t *testing.T) {
convey.Convey("SendWechat", t, func(ctx convey.C) {
var (
param map[string]int64
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.SendWechat(param)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaosign(t *testing.T) {
convey.Convey("sign", t, func(ctx convey.C) {
var (
params map[string]string
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := d.sign(params)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,34 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["http.go"],
importpath = "go-common/app/job/main/passport-user-compare/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/passport-user-compare/conf:go_default_library",
"//app/job/main/passport-user-compare/service:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster: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"],
)

View File

@@ -0,0 +1,46 @@
package http
import (
"net/http"
"go-common/app/job/main/passport-user-compare/conf"
"go-common/app/job/main/passport-user-compare/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
var (
srv *service.Service
)
// Init init http sever instance.
func Init(c *conf.Config) {
initService(c)
// init inner router
// engine
engIn := bm.DefaultServer(c.BM)
innerRouter(engIn)
// init inner server
if err := engIn.Start(); err != nil {
log.Error("bm.DefaultServer error(%v)", err)
panic(err)
}
}
// initService init services.
func initService(c *conf.Config) {
srv = service.New(c)
}
// innerRouter init inner router.
func innerRouter(e *bm.Engine) {
e.Ping(ping)
}
// ping check server ok.
func ping(c *bm.Context) {
if err := srv.Ping(c); err != nil {
log.Error("ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}

View File

@@ -0,0 +1,34 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"origin.go",
"secret.go",
"stat.go",
"user.go",
],
importpath = "go-common/app/job/main/passport-user-compare/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["//library/time: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"],
)

View File

@@ -0,0 +1,63 @@
package model
import "go-common/library/time"
// OriginAccount origin aso account.
type OriginAccount struct {
Mid int64 `json:"mid"`
UserID string `json:"userid"`
Uname string `json:"uname"`
Pwd string `json:"pwd"`
Salt string `json:"salt"`
Email string `json:"email"`
Tel string `json:"tel"`
CountryID int64 `json:"country_id"`
MobileVerified int8 `json:"mobile_verified"`
Isleak int8 `json:"isleak"`
MTime time.Time `json:"modify_time"`
}
// OriginAccountInfo origin aso account info.
type OriginAccountInfo struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Spacesta int8 `json:"spacesta"`
SafeQuestion int8 `json:"safe_question"`
SafeAnswer string `json:"safe_answer"`
JoinTime int64 `json:"join_time"`
JoinIP string `json:"join_ip"`
ActiveTime int64 `json:"active_time"`
MTime time.Time `json:"modify_time"`
}
// OriginAccountReg origin aso account reg.
type OriginAccountReg struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
OriginType int8 `json:"origintype"`
RegType int8 `json:"regtype"`
AppID int64 `json:"appid"`
CTime time.Time `json:"active_time"`
MTime time.Time `json:"modify_time"`
}
// OriginAccountSns origin aso account sns.
type OriginAccountSns struct {
Mid int64 `json:"mid"`
SinaUID int64 `json:"sina_uid"`
SinaAccessToken string `json:"sina_access_token"`
SinaAccessExpires int64 `json:"sina_access_expires"`
QQOpenid string `json:"qq_openid"`
QQAccessToken string `json:"qq_access_token"`
QQAccessExpires int64 `json:"qq_access_expires"`
}
// CountryCode aso country code.
type CountryCode struct {
ID int64 `json:"id"`
Code string `json:"code"`
Cname string `json:"cname"`
Rank int64 `json:"rank"`
Type int8 `json:"type"`
Ename string `json:"ename"`
}

View File

@@ -0,0 +1,7 @@
package model
// Secret secret
type Secret struct {
KeyType int8 `json:"key_type"`
Key string `json:"key"`
}

View File

@@ -0,0 +1,14 @@
package model
// Stat stat
type Stat struct {
Total int64 `json:"total"`
ErrorType int64 `json:"error_type"`
}
// ErrorFix error fix
type ErrorFix struct {
Action string `json:"action"`
Mid int64 `json:"mid"`
ErrorType int64 `json:"error_type"`
}

View File

@@ -0,0 +1,91 @@
package model
import "go-common/library/time"
// UserBase user base.
type UserBase struct {
Mid int64 `json:"mid"`
UserID string `json:"userid"`
Pwd []byte `json:"pwd"`
Salt string `json:"salt"`
Status int8 `json:"status"`
Deleted int8 `json:"deleted"`
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}
// UserEmail user email.
type UserEmail struct {
Mid int64 `json:"mid"`
Email []byte `json:"email"`
Verified int8 `json:"verified"`
EmailBindTime int64 `json:"email_bind_time"`
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}
// UserTel user tel.
type UserTel struct {
Mid int64 `json:"mid"`
Tel []byte `json:"tel"`
Cid string `json:"cid"`
TelBindTime int64 `json:"tel_bind_time"`
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}
// UserRegOrigin user reg origin.
type UserRegOrigin struct {
Mid int64 `json:"mid"`
JoinIP int64 `json:"join_ip"`
JoinTime int64 `json:"join_time"`
Origin int8 `json:"origin"`
RegType int8 `json:"reg_type"`
AppID int64 `json:"appid"`
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}
// UserSafeQuestion user safe question.
type UserSafeQuestion struct {
Mid int64 `json:"mid"`
SafeQuestion int8 `json:"safe_question"`
SafeAnswer []byte `json:"safe_answer"`
SafeBindTime int64 `json:"safe_bind_time"`
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}
// UserThirdBind user third bind.
type UserThirdBind struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
OpenID string `json:"openid"`
PlatForm int64 `json:"platform"`
Token string `json:"token"`
Expires int64 `json:"expires"`
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}
// UserTelDuplicate user tel duplicate.
type UserTelDuplicate struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Tel []byte `json:"tel"`
Cid string `json:"cid"`
TelBindTime int64 `json:"tel_bind_time"`
Status int8 `json:"status"`
Timestamp int64 `json:"ts"`
}
// UserEmailDuplicate user email duplicate.
type UserEmailDuplicate struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Email []byte `json:"email"`
Verified int32 `json:"verified"`
EmailBindTime int64 `json:"email_bind_time"`
Status int8 `json:"status"`
Timestamp int64 `json:"ts"`
}

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