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,25 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/main/spy/api:all-srcs",
"//app/service/main/spy/cmd:all-srcs",
"//app/service/main/spy/conf:all-srcs",
"//app/service/main/spy/dao:all-srcs",
"//app/service/main/spy/model:all-srcs",
"//app/service/main/spy/rpc/client:all-srcs",
"//app/service/main/spy/rpc/server:all-srcs",
"//app/service/main/spy/server/grpc:all-srcs",
"//app/service/main/spy/server/http:all-srcs",
"//app/service/main/spy/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,117 @@
反作弊项目-服务
v1.7.2
1. update http server pkg
v1.7.1
1. 添加grpc接口
v1.7.0
1. 更新基础分计算策略,支持实名认证和福利社绑定检查
2. 支持基础分刷新操作
v1.6.1
1. dao unit test
v1.6.0
1. 改为 metadata RemoteIP
v1.5.3
1. stat rpc group by event
v1.5.2
1. 添加stat rpc接口
v1.5.0
1. purgeUser v2
v1.4.5
1. add register
v1.4.4
1. 异步更新基础分
v1.4.3
1. refined log
v1.4.2
1. add tel white list
2. mv repo path
v1.4.1
1. update account info to card
v1.4.0
1. http bm
2. code refined
v1.3.2
1. remove account-service
2. use account audit
v1.3.1
1. remove stastd
v1.3.0
1. 腾讯天域手机号验证
v1.2.5
1. update handle event logic
v1.2.4
1. 修改用户初始化SQL
v1.2.3
1. 反作弊案件
v1.2.2
1. 优化identify
v1.2.1
1. add mc,db,httpclient prom
v1.2.0
1. 真实分信息接口异步化
v1.1.9
1. 增加二次登陆验证的cd期
v1.1.8
1. 报表及监控
v1.1.7
1. 加入dapper
v1.1.6
1. 二次验证获取账号信息的重试
v1.1.5
1. 反作弊变更databus
v1.1.4
1. asyn 初始化用户信息
v1.1.3
1. 修改event msg 参数名
v1.1.2
1. 导入二次登陆,备注调整
v1.1.1
1. 自动封禁系统中,增加过滤条件
v1.1.0
1. 反作弊二期,自动封禁相关
v1.0.3
1. 修复mc ping
v1.0.2
1. 迁移大仓库
v1.0.1
1. 更改purge method
v1.0.0
1. 初始化项目,更新依赖
2. 完成反作弊一期开发

View File

@ -0,0 +1,11 @@
# Owner
zhaogangtao
# Author
zhaogangtao
yubaihai
muyang
# Reviewer
linmiao
zhaogangtao

View File

@ -0,0 +1,17 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- muyang
- yubaihai
- zhaogangtao
labels:
- main
- service
- service/main/spy
options:
no_parent_owners: true
reviewers:
- linmiao
- muyang
- yubaihai
- zhaogangtao

View File

@ -0,0 +1,13 @@
#### archive-service
##### 项目简介
> 1.提供反作弊服务
##### 编译环境
> 请只用golang v1.7.x以上版本编译执行。
##### 依赖包
> 1.公共包go-common
##### 特别说明
> 1.model目录可能会被其他项目引用请谨慎请改并通知各方。

View File

@ -0,0 +1,60 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
proto_library(
name = "v1_proto",
srcs = ["api.proto"],
tags = ["automanaged"],
)
go_proto_library(
name = "v1_go_proto",
compilers = ["@io_bazel_rules_go//proto:go_grpc"],
importpath = "go-common/app/service/main/spy/api",
proto = ":v1_proto",
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = [
"client.go",
"copy.go",
"doc.go",
],
embed = [":v1_go_proto"],
importpath = "go-common/app/service/main/spy/api",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/spy/model:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/time:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_x_net//context: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"],
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,186 @@
syntax = "proto3";
package account.spy;
option go_package = "v1";
message ClearReliveTimesReply {
}
message ClearReliveTimesReq {
ModelArgReset arg = 1;
}
message HandleEventReply {
}
message HandleEventReq {
ModelEventMessage event_msg = 1;
}
message ModelArgReset {
int64 mid = 1;
bool re_live_time = 2;
bool event_score = 3;
bool base_score = 4;
string operator = 5;
}
message ModelEventMessage {
int64 time = 1;
string ip = 2;
string service = 3;
string event = 4;
int64 active_mid = 5;
int64 target_mid = 6;
int64 target_id = 7;
//FIXME type model. args = 8;
string result = 9;
string effect = 10;
int32 risk_level = 11;
}
message ModelStatistics {
int64 quantity = 1;
int64 event_id = 2;
string event_name = 3;
}
message ModelUserInfo {
int64 id = 1;
int64 mid = 2;
int32 score = 3;
int32 base_score = 4;
int32 event_score = 5;
int32 state = 6;
int32 relive_times = 7;
int64 ctime = 8;
int64 mtime = 9;
}
message PingReply {
}
message PingReq {
}
message PurgeUserReply {
}
message PurgeUserReq {
int64 mid = 1;
string action = 2;
}
message ReBuildPortraitReply {
}
message ReBuildPortraitReq {
int64 mid = 1;
string reason = 2;
}
message RefreshBaseScoreReply {
}
message RefreshBaseScoreReq {
ModelArgReset arg = 1;
}
message StatByIDGroupEventReply {
repeated ModelStatistics res = 1;
}
message StatByIDGroupEventReq {
int64 mid = 1;
int64 id = 2;
}
message StatByIDReply {
repeated ModelStatistics stat = 1;
}
message StatByIDReq {
int64 mid = 1;
int64 id = 2;
}
message UpdateBaseScoreReply {
}
message UpdateBaseScoreReq {
ModelArgReset arg = 1;
}
message UpdateEventScoreReply {
}
message UpdateEventScoreReq {
ModelArgReset arg = 1;
}
message UpdateUserScoreReply {
}
message UpdateUserScoreReq {
int64 mid = 1;
string ip = 2;
string effect = 3;
}
message UserInfoAsynReply {
ModelUserInfo ui = 1;
}
message UserInfoAsynReq {
int64 mid = 1;
}
message UserInfoReply {
ModelUserInfo ui = 1;
}
message UserInfoReq {
int64 mid = 1;
string ip = 2;
}
message InfoReq {
int64 mid = 1;
}
message InfoReply {
ModelUserInfo ui = 1;
}
service Spy {
// Ping check dao health.
rpc Ping(PingReq) returns(PingReply);
// Info get user info by mid.
rpc Info(InfoReq) returns(InfoReply);
// StatByID spy stat by id or mid.
rpc StatByID(StatByIDReq) returns(StatByIDReply);
// StatByIDGroupEvent spy stat by id or mid.
rpc StatByIDGroupEvent(StatByIDGroupEventReq) returns(StatByIDGroupEventReply);
// PurgeUser purge user info
rpc PurgeUser(PurgeUserReq) returns(PurgeUserReply);
// HandleEvent handle spy-event.
rpc HandleEvent(HandleEventReq) returns(HandleEventReply);
// UserInfo get UserInfo by mid , from cache or db or generate.
rpc UserInfo(UserInfoReq) returns(UserInfoReply);
// UserInfoAsyn get UserInfo by mid , from cache or db or asyn generate.
rpc UserInfoAsyn(UserInfoAsynReq) returns(UserInfoAsynReply);
// ReBuildPortrait reBuild user info.
rpc ReBuildPortrait(ReBuildPortraitReq) returns(ReBuildPortraitReply);
// UpdateUserScore update user score
rpc UpdateUserScore(UpdateUserScoreReq) returns(UpdateUserScoreReply);
// RefreshBaseScore refresh base score.
rpc RefreshBaseScore(RefreshBaseScoreReq) returns(RefreshBaseScoreReply);
// UpdateBaseScore update base score.
rpc UpdateBaseScore(UpdateBaseScoreReq) returns(UpdateBaseScoreReply);
// UpdateEventScore update event score.
rpc UpdateEventScore(UpdateEventScoreReq) returns(UpdateEventScoreReply);
// ClearReliveTimes clear times.
rpc ClearReliveTimes(ClearReliveTimesReq) returns(ClearReliveTimesReply);
}

View File

@ -0,0 +1,22 @@
package v1
import (
"context"
"google.golang.org/grpc"
"go-common/library/net/rpc/warden"
)
// AppID unique app id for service discovery
const AppID = "account.service.spy"
// NewClient new identify grpc client
func NewClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (SpyClient, error) {
client := warden.NewClient(cfg, opts...)
conn, err := client.Dial(context.Background(), "discovery://default/"+AppID)
if err != nil {
return nil, err
}
return NewSpyClient(conn), nil
}

View File

@ -0,0 +1,961 @@
// +build !ignore_autogenerated
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1
import (
model "go-common/app/service/main/spy/model"
"go-common/library/time"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClearReliveTimesReply) DeepCopyInto(out *ClearReliveTimesReply) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClearReliveTimesReply.
func (in *ClearReliveTimesReply) DeepCopy() *ClearReliveTimesReply {
if in == nil {
return nil
}
out := new(ClearReliveTimesReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClearReliveTimesReq) DeepCopyInto(out *ClearReliveTimesReq) {
*out = *in
if in.Arg != nil {
in, out := &in.Arg, &out.Arg
*out = new(ModelArgReset)
(*in).DeepCopyInto(*out)
}
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClearReliveTimesReq.
func (in *ClearReliveTimesReq) DeepCopy() *ClearReliveTimesReq {
if in == nil {
return nil
}
out := new(ClearReliveTimesReq)
in.DeepCopyInto(out)
return out
}
func (in *ClearReliveTimesReq) DeepCopyAsIntoArgReset(out *model.ArgReset) {
if out == nil {
return
}
out.Mid = in.Arg.Mid
out.BaseScore = in.Arg.BaseScore
out.EventScore = in.Arg.EventScore
out.Operator = in.Arg.Operator
out.ReLiveTime = in.Arg.ReLiveTime
return
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HandleEventReply) DeepCopyInto(out *HandleEventReply) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HandleEventReply.
func (in *HandleEventReply) DeepCopy() *HandleEventReply {
if in == nil {
return nil
}
out := new(HandleEventReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HandleEventReq) DeepCopyInto(out *HandleEventReq) {
*out = *in
if in.EventMsg != nil {
in, out := &in.EventMsg, &out.EventMsg
*out = new(ModelEventMessage)
(*in).DeepCopyInto(*out)
}
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
func (in *HandleEventReq) DeepCopyAsIntoEventMessage(out *model.EventMessage) {
if out == nil {
return
}
out.Time = time.Time(in.EventMsg.Time)
out.IP = in.EventMsg.Ip
out.Service = in.EventMsg.Service
out.Event = in.EventMsg.Event
out.ActiveMid = in.EventMsg.ActiveMid
out.TargetMid = in.EventMsg.TargetMid
out.TargetID = in.EventMsg.TargetId
out.Result = in.EventMsg.Result
out.Effect = in.EventMsg.Effect
out.RiskLevel = int8(in.EventMsg.RiskLevel)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HandleEventReq.
func (in *HandleEventReq) DeepCopy() *HandleEventReq {
if in == nil {
return nil
}
out := new(HandleEventReq)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ModelArgReset) DeepCopyInto(out *ModelArgReset) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ModelArgReset.
func (in *ModelArgReset) DeepCopy() *ModelArgReset {
if in == nil {
return nil
}
out := new(ModelArgReset)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ModelEventMessage) DeepCopyInto(out *ModelEventMessage) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ModelEventMessage.
func (in *ModelEventMessage) DeepCopy() *ModelEventMessage {
if in == nil {
return nil
}
out := new(ModelEventMessage)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ModelStatistics) DeepCopyInto(out *ModelStatistics) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ModelStatistics.
func (in *ModelStatistics) DeepCopy() *ModelStatistics {
if in == nil {
return nil
}
out := new(ModelStatistics)
in.DeepCopyInto(out)
return out
}
// DeepCopyAsIntoStatistics is an autogenerated deepcopy function, copying the receiver, writing into model.Statistics.
func (in *ModelStatistics) DeepCopyAsIntoStatistics(out *model.Statistics) {
out.Quantity = in.Quantity
out.EventName = in.EventName
return
}
// DeepCopyFromStatistics is an autogenerated deepcopy function, copying the receiver, writing into model.Statistics.
func (out *ModelStatistics) DeepCopyFromStatistics(in *model.Statistics) {
out.Quantity = in.Quantity
out.EventId = in.EventID
out.EventName = in.EventName
return
}
// DeepCopyAsStatistics is an autogenerated deepcopy function, copying the receiver, creating a new model.Statistics.
func (in *ModelStatistics) DeepCopyAsStatistics() *model.Statistics {
if in == nil {
return nil
}
out := new(model.Statistics)
in.DeepCopyAsIntoStatistics(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ModelUserInfo) DeepCopyInto(out *ModelUserInfo) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ModelUserInfo.
func (in *ModelUserInfo) DeepCopy() *ModelUserInfo {
if in == nil {
return nil
}
out := new(ModelUserInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyAsIntoUserInfo is an autogenerated deepcopy function, copying the receiver, writing into model.UserInfo.
func (in *ModelUserInfo) DeepCopyAsIntoUserInfo(out *model.UserInfo) {
out.Mid = in.Mid
return
}
// DeepCopyFromUserInfo is an autogenerated deepcopy function, copying the receiver, writing into model.UserInfo.
func (out *ModelUserInfo) DeepCopyFromUserInfo(in *model.UserInfo) {
if in == nil {
return
}
out.Mid = in.Mid
out.Id = in.ID
out.Score = int32(in.Score)
out.BaseScore = int32(in.BaseScore)
out.EventScore = int32(in.EventScore)
out.State = int32(in.State)
out.ReliveTimes = int32(in.ReliveTimes)
out.Ctime = int64(in.CTime)
out.Mtime = int64(in.MTime)
return
}
// DeepCopyAsUserInfo is an autogenerated deepcopy function, copying the receiver, creating a new model.UserInfo.
func (in *ModelUserInfo) DeepCopyAsUserInfo() *model.UserInfo {
if in == nil {
return nil
}
out := new(model.UserInfo)
in.DeepCopyAsIntoUserInfo(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PingReply) DeepCopyInto(out *PingReply) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PingReply.
func (in *PingReply) DeepCopy() *PingReply {
if in == nil {
return nil
}
out := new(PingReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PingReq) DeepCopyInto(out *PingReq) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PingReq.
func (in *PingReq) DeepCopy() *PingReq {
if in == nil {
return nil
}
out := new(PingReq)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PurgeUserReply) DeepCopyInto(out *PurgeUserReply) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PurgeUserReply.
func (in *PurgeUserReply) DeepCopy() *PurgeUserReply {
if in == nil {
return nil
}
out := new(PurgeUserReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PurgeUserReq) DeepCopyInto(out *PurgeUserReq) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PurgeUserReq.
func (in *PurgeUserReq) DeepCopy() *PurgeUserReq {
if in == nil {
return nil
}
out := new(PurgeUserReq)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ReBuildPortraitReply) DeepCopyInto(out *ReBuildPortraitReply) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReBuildPortraitReply.
func (in *ReBuildPortraitReply) DeepCopy() *ReBuildPortraitReply {
if in == nil {
return nil
}
out := new(ReBuildPortraitReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ReBuildPortraitReq) DeepCopyInto(out *ReBuildPortraitReq) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReBuildPortraitReq.
func (in *ReBuildPortraitReq) DeepCopy() *ReBuildPortraitReq {
if in == nil {
return nil
}
out := new(ReBuildPortraitReq)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RefreshBaseScoreReply) DeepCopyInto(out *RefreshBaseScoreReply) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RefreshBaseScoreReply.
func (in *RefreshBaseScoreReply) DeepCopy() *RefreshBaseScoreReply {
if in == nil {
return nil
}
out := new(RefreshBaseScoreReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RefreshBaseScoreReq) DeepCopyInto(out *RefreshBaseScoreReq) {
*out = *in
if in.Arg != nil {
in, out := &in.Arg, &out.Arg
*out = new(ModelArgReset)
(*in).DeepCopyInto(*out)
}
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RefreshBaseScoreReq.
func (in *RefreshBaseScoreReq) DeepCopy() *RefreshBaseScoreReq {
if in == nil {
return nil
}
out := new(RefreshBaseScoreReq)
in.DeepCopyInto(out)
return out
}
func (in *RefreshBaseScoreReq) DeepCopyAsIntoArgReset(out *model.ArgReset) {
if out == nil {
return
}
out.Mid = in.Arg.Mid
out.BaseScore = in.Arg.BaseScore
out.EventScore = in.Arg.EventScore
out.Operator = in.Arg.Operator
out.ReLiveTime = in.Arg.ReLiveTime
return
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StatByIDGroupEventReply) DeepCopyInto(out *StatByIDGroupEventReply) {
*out = *in
if in.Res != nil {
in, out := &in.Res, &out.Res
*out = make([]*ModelStatistics, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(ModelStatistics)
(*in).DeepCopyInto(*out)
}
}
}
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatByIDGroupEventReply.
func (in *StatByIDGroupEventReply) DeepCopy() *StatByIDGroupEventReply {
if in == nil {
return nil
}
out := new(StatByIDGroupEventReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyAsIntoStatistics is an autogenerated deepcopy function, copying the receiver, writing into model.Statistics.
func (in *StatByIDGroupEventReply) DeepCopyAsIntoStatistics(out *model.Statistics) {
return
}
// DeepCopyFromStatistics is an autogenerated deepcopy function, copying the receiver, writing into model.Statistics.
func (out *StatByIDGroupEventReply) DeepCopyFromStatistics(in []*model.Statistics) {
out.Res = make([]*ModelStatistics, 0, len(in))
for _, v := range in {
statistic := new(ModelStatistics)
statistic.DeepCopyFromStatistics(v)
out.Res = append(out.Res, statistic)
}
return
}
// DeepCopyAsStatistics is an autogenerated deepcopy function, copying the receiver, creating a new model.Statistics.
func (in *StatByIDGroupEventReply) DeepCopyAsStatistics() *model.Statistics {
if in == nil {
return nil
}
out := new(model.Statistics)
in.DeepCopyAsIntoStatistics(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StatByIDGroupEventReq) DeepCopyInto(out *StatByIDGroupEventReq) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatByIDGroupEventReq.
func (in *StatByIDGroupEventReq) DeepCopy() *StatByIDGroupEventReq {
if in == nil {
return nil
}
out := new(StatByIDGroupEventReq)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StatByIDReply) DeepCopyInto(out *StatByIDReply) {
*out = *in
if in.Stat != nil {
in, out := &in.Stat, &out.Stat
*out = make([]*ModelStatistics, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(ModelStatistics)
(*in).DeepCopyInto(*out)
}
}
}
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatByIDReply.
func (in *StatByIDReply) DeepCopy() *StatByIDReply {
if in == nil {
return nil
}
out := new(StatByIDReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyAsIntoStatistics is an autogenerated deepcopy function, copying the receiver, writing into model.Statistics.
func (in *StatByIDReply) DeepCopyAsIntoStatistics(out *model.Statistics) {
return
}
// DeepCopyFromStatistics is an autogenerated deepcopy function, copying the receiver, writing into model.Statistics.
func (out *StatByIDReply) DeepCopyFromStatistics(in []*model.Statistics) {
out.Stat = make([]*ModelStatistics, 0, len(in))
for _, v := range in {
statistic := new(ModelStatistics)
statistic.DeepCopyFromStatistics(v)
out.Stat = append(out.Stat, statistic)
}
return
}
// DeepCopyAsStatistics is an autogenerated deepcopy function, copying the receiver, creating a new model.Statistics.
func (in *StatByIDReply) DeepCopyAsStatistics() *model.Statistics {
if in == nil {
return nil
}
out := new(model.Statistics)
in.DeepCopyAsIntoStatistics(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StatByIDReq) DeepCopyInto(out *StatByIDReq) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatByIDReq.
func (in *StatByIDReq) DeepCopy() *StatByIDReq {
if in == nil {
return nil
}
out := new(StatByIDReq)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdateBaseScoreReply) DeepCopyInto(out *UpdateBaseScoreReply) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateBaseScoreReply.
func (in *UpdateBaseScoreReply) DeepCopy() *UpdateBaseScoreReply {
if in == nil {
return nil
}
out := new(UpdateBaseScoreReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdateBaseScoreReq) DeepCopyInto(out *UpdateBaseScoreReq) {
*out = *in
if in.Arg != nil {
in, out := &in.Arg, &out.Arg
*out = new(ModelArgReset)
(*in).DeepCopyInto(*out)
}
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateBaseScoreReq.
func (in *UpdateBaseScoreReq) DeepCopy() *UpdateBaseScoreReq {
if in == nil {
return nil
}
out := new(UpdateBaseScoreReq)
in.DeepCopyInto(out)
return out
}
func (in *UpdateBaseScoreReq) DeepCopyAsIntoArgReset(out *model.ArgReset) {
if out == nil {
return
}
out.Mid = in.Arg.Mid
out.BaseScore = in.Arg.BaseScore
out.EventScore = in.Arg.EventScore
out.Operator = in.Arg.Operator
out.ReLiveTime = in.Arg.ReLiveTime
return
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdateEventScoreReply) DeepCopyInto(out *UpdateEventScoreReply) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateEventScoreReply.
func (in *UpdateEventScoreReply) DeepCopy() *UpdateEventScoreReply {
if in == nil {
return nil
}
out := new(UpdateEventScoreReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdateEventScoreReq) DeepCopyInto(out *UpdateEventScoreReq) {
*out = *in
if in.Arg != nil {
in, out := &in.Arg, &out.Arg
*out = new(ModelArgReset)
(*in).DeepCopyInto(*out)
}
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateEventScoreReq.
func (in *UpdateEventScoreReq) DeepCopy() *UpdateEventScoreReq {
if in == nil {
return nil
}
out := new(UpdateEventScoreReq)
in.DeepCopyInto(out)
return out
}
func (in *UpdateEventScoreReq) DeepCopyAsIntoArgReset(out *model.ArgReset) {
if out == nil {
return
}
out.Mid = in.Arg.Mid
out.BaseScore = in.Arg.BaseScore
out.EventScore = in.Arg.EventScore
out.Operator = in.Arg.Operator
out.ReLiveTime = in.Arg.ReLiveTime
return
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdateUserScoreReply) DeepCopyInto(out *UpdateUserScoreReply) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateUserScoreReply.
func (in *UpdateUserScoreReply) DeepCopy() *UpdateUserScoreReply {
if in == nil {
return nil
}
out := new(UpdateUserScoreReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdateUserScoreReq) DeepCopyInto(out *UpdateUserScoreReq) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateUserScoreReq.
func (in *UpdateUserScoreReq) DeepCopy() *UpdateUserScoreReq {
if in == nil {
return nil
}
out := new(UpdateUserScoreReq)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UserInfoAsynReply) DeepCopyInto(out *UserInfoAsynReply) {
*out = *in
if in.Ui != nil {
in, out := &in.Ui, &out.Ui
*out = new(ModelUserInfo)
(*in).DeepCopyInto(*out)
}
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserInfoAsynReply.
func (in *UserInfoAsynReply) DeepCopy() *UserInfoAsynReply {
if in == nil {
return nil
}
out := new(UserInfoAsynReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyAsIntoUserInfo is an autogenerated deepcopy function, copying the receiver, writing into model.UserInfo.
func (in *UserInfoAsynReply) DeepCopyAsIntoUserInfo(out *model.UserInfo) {
return
}
// DeepCopyFromUserInfo is an autogenerated deepcopy function, copying the receiver, writing into model.UserInfo.
func (out *UserInfoAsynReply) DeepCopyFromUserInfo(in *model.UserInfo) {
if in == nil {
return
}
out.Ui = new(ModelUserInfo)
out.Ui.DeepCopyFromUserInfo(in)
return
}
// DeepCopyAsUserInfo is an autogenerated deepcopy function, copying the receiver, creating a new model.UserInfo.
func (in *UserInfoAsynReply) DeepCopyAsUserInfo() *model.UserInfo {
if in == nil {
return nil
}
out := new(model.UserInfo)
in.DeepCopyAsIntoUserInfo(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UserInfoAsynReq) DeepCopyInto(out *UserInfoAsynReq) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserInfoAsynReq.
func (in *UserInfoAsynReq) DeepCopy() *UserInfoAsynReq {
if in == nil {
return nil
}
out := new(UserInfoAsynReq)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UserInfoReply) DeepCopyInto(out *UserInfoReply) {
*out = *in
if in.Ui != nil {
in, out := &in.Ui, &out.Ui
*out = new(ModelUserInfo)
(*in).DeepCopyInto(*out)
}
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserInfoReply.
func (in *UserInfoReply) DeepCopy() *UserInfoReply {
if in == nil {
return nil
}
out := new(UserInfoReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyAsIntoUserInfo is an autogenerated deepcopy function, copying the receiver, writing into model.UserInfo.
func (in *UserInfoReply) DeepCopyAsIntoUserInfo(out *model.UserInfo) {
return
}
// DeepCopyFromUserInfo is an autogenerated deepcopy function, copying the receiver, writing into model.UserInfo.
func (out *UserInfoReply) DeepCopyFromUserInfo(in *model.UserInfo) {
if in == nil {
return
}
out.Ui = new(ModelUserInfo)
out.Ui.DeepCopyFromUserInfo(in)
return
}
// DeepCopyAsUserInfo is an autogenerated deepcopy function, copying the receiver, creating a new model.UserInfo.
func (in *UserInfoReply) DeepCopyAsUserInfo() *model.UserInfo {
if in == nil {
return nil
}
out := new(model.UserInfo)
in.DeepCopyAsIntoUserInfo(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UserInfoReq) DeepCopyInto(out *UserInfoReq) {
*out = *in
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
if in.XXX_unrecognized != nil {
in, out := &in.XXX_unrecognized, &out.XXX_unrecognized
*out = make([]byte, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserInfoReq.
func (in *UserInfoReq) DeepCopy() *UserInfoReq {
if in == nil {
return nil
}
out := new(UserInfoReq)
in.DeepCopyInto(out)
return out
}
func (out *InfoReply) DeepCopyFromUserInfo(in *model.UserInfo) {
if in == nil {
return
}
out.Ui = new(ModelUserInfo)
out.Ui.DeepCopyFromUserInfo(in)
return
}

View File

@ -0,0 +1,2 @@
// +bili:deepcopy-gen=package
package v1

View File

@ -0,0 +1,49 @@
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 = ["spy-service-test.toml"],
importpath = "go-common/app/service/main/spy/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/spy/conf:go_default_library",
"//app/service/main/spy/rpc/server:go_default_library",
"//app/service/main/spy/server/grpc:go_default_library",
"//app/service/main/spy/server/http:go_default_library",
"//app/service/main/spy/service:go_default_library",
"//library/log:go_default_library",
"//library/net/rpc:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/trace:go_default_library",
"//library/os/signal:go_default_library",
"//library/syscall: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,61 @@
package main
import (
"flag"
"os"
"time"
"go-common/app/service/main/spy/conf"
rpc "go-common/app/service/main/spy/rpc/server"
grpc "go-common/app/service/main/spy/server/grpc"
"go-common/app/service/main/spy/server/http"
"go-common/app/service/main/spy/service"
"go-common/library/log"
xrpc "go-common/library/net/rpc"
"go-common/library/net/rpc/warden"
"go-common/library/net/trace"
"go-common/library/os/signal"
"go-common/library/syscall"
)
var (
svr *service.Service
rpcSvr *xrpc.Server
grpcSvr *warden.Server
)
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()
trace.Init(conf.Conf.Tracer)
defer trace.Close()
// service init
svr = service.New(conf.Conf)
http.Init(conf.Conf, svr)
rpcSvr = rpc.New(conf.Conf, svr)
grpcSvr = grpc.New(conf.Conf.GRPC, svr)
log.Info("spy-service start")
// init signal
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT, syscall.SIGSTOP)
for {
s := <-c
log.Info("spy-service get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGSTOP, syscall.SIGINT:
rpcSvr.Close()
time.Sleep(time.Second * 2)
log.Info("spy-service exit")
return
case syscall.SIGHUP:
// TODO reload
default:
return
}
}
}

View File

@ -0,0 +1,182 @@
version = "1.0.0"
user = "nobody"
pid = "/tmp/spy-service.pid"
dir = "./"
checkFile = "/data/www/spy-service.html"
family = "spy-service"
account = "http://passport.bilibili.co"
[xlog]
dir = "/data/log/spy-service"
[db]
[db.spy]
addr= "172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_spy?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
idleTimeout ="4h"
queryTimeout = "100ms"
execTimeout = "100ms"
tranTimeout = "200ms"
[db.spy.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[rpc]
[rpc.account]
[bm]
[bm.inner]
addr = "0.0.0.0:7651"
maxListen = 10
timeout = "1s"
[httpClient]
dial = "1s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
key = "zxnh4k92dwe61t27"
secret = "dnu3bwpxyswqwf1ixpsczthury1nqiew"
[httpClient.breaker]
window = "3s"
sleep = "500ms"
bucket = 10
ratio = 0.5
request = 100
switchoff = false
[identify]
[identify.host]
auth = "http://passport.bilibili.co"
secret = "http://open.bilibili.co"
[identify.httpClient]
key = "zxnh4k92dwe61t27"
secret = "dnu3bwpxyswqwf1ixpsczthury1nqiew"
dial = "30ms"
timeout = "100ms"
keepAlive = "60s"
[identify.httpClient.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[identify.httpClient.url]
"http://passport.bilibili.co/intranet/auth/tokenInfo" = {timeout = "100ms"}
"http://passport.bilibili.co/intranet/auth/cookieInfo" = {timeout = "100ms"}
"http://open.bilibili.co/api/getsecret" = {timeout = "500ms"}
[rpcServer2]
[[rpcServer2.servers]]
proto = "tcp"
addr = "0.0.0.0:6869"
weight = 10
[rpcServer2.zookeeper]
root = "/microservice/spy-service/"
addrs = ["172.18.33.172:2181"]
timeout = "30s"
[memcache]
userExpire = "1m"
[memcache.user]
name = "spy-service/user"
proto = "tcp"
addr = "172.16.33.22:21211"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
[property]
telValidateURL = "http://passport.bilibili.co/intranet/acc/validateTel"
blockAccountURL = "https://account.bilibili.com/api/member/blockAccount"
securityLoginURL = "http://passport.bilibili.co/intranet/acc/security/mid"
telInfoByMidURL = "http://passport.bilibili.co/intranet/acc/telInfo/mid"
profileInfoByMidURL = "http://api.bilibili.co/x/internal/v3/account/profile"
unicomGiftStateURL = "http://app.bilibili.com/x/wall/unicom/bind/state"
loadEventTick = "60s"
doubleCheckLevel = 4
configLoadTick = "60s"
userInfoShard = 100
historyShard = 100
autoBlockSwitch = true
[property.score]
baseInit = 100
eventInit = 100
[property.punishment]
scoreThreshold = 30
times = 3
[property.event]
serviceName = "spy_service"
initEventID = 1
bindMailAndTelLowRisk = "bind_mail_and_tel_low_risk"
bindMailOnly = "bind_mail_only"
bindNothing = "bind_nothing"
bindTelLowRiskOnly = "bind_tel_low_risk_only"
bindTelMediumRisk = "bind_tel_medium_risk"
bindTelHighRisk = "bind_tel_high_risk"
bindTelUnknownRisk = "bind_tel_unknown_risk"
bindTelLowRiskAndIdenAuth = "bind_tel_low_risk_and_iden_auth"
bindTelLowRiskAndIdenUnauth = "bind_tel_low_risk_and_iden_unauth"
bindTelUnknownRiskAndIdenAuth = "bind_tel_unknown_risk_and_iden_auth"
bindTelMediumRiskAndIdenAuth = "bind_tel_medium_risk_and_iden_auth"
bindTelUnknownRiskAndIdenUnauth = "bind_tel_unknown_risk_and_iden_unauth"
bindTelMediumRiskAndIdenUnauth = "bind_tel_medium_risk_and_iden_unauth"
bindMailAndIdenUnknown = "bind_mail_and_iden_unknown"
bindTelHighRiskAndIdenAuth = "bind_tel_high_risk_and_iden_auth"
bindNothingV2 = "bind_nothing_v2"
bindNothingAndIdenAuth = "bind_nothing_and_iden_auth"
bindTelHighRiskAndIdenUnauth = "bind_tel_high_risk_and_iden_unauth"
[property.block]
cycleTimes = 3600
[property.white]
[[property.white.tels]]
from = 23333330000
to = 23333340000
[redis]
name = "spy-service"
proto = "tcp"
addr = "172.16.33.54:6379"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
verifyCdTimes = "2h"
[dBScoreChange]
key = "0QNB0ZgFozbKUCQhbTq8"
secret= "0QNB0ZgFozbKUCQhbTq9"
group= "SpyFigure-UGC-P"
topic= "SpyFigure-T"
action="pub"
name = "spy-service/databus"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 2
active = 10
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
[qcloud]
path = "RegisterProtection"
region = "sh"
secretID = ""
secretKey = ""
charset = "utf-8"
baseURL = "csec.api.qcloud.com/v2/index.php"

View File

@ -0,0 +1,51 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["conf_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/service/main/spy/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//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/rpc:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus: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,196 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/conf"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/rpc"
"go-common/library/net/trace"
"go-common/library/queue/databus"
"go-common/library/time"
xtime "go-common/library/time"
"go-common/library/net/rpc/warden"
"github.com/BurntSushi/toml"
)
var (
confPath string
client *conf.Client
// Conf represents a config for spy service.
Conf = &Config{}
)
// Config def.
type Config struct {
Account string
// tracer
Tracer *trace.Config
// http client
HTTPClient *bm.ClientConfig
// db
DB *DB
// rpc server2
RPCServer *rpc.ServerConfig
// memcache
Memcache *Memcache
// log
Log *log.Config
// rpc clients
RPC *RPC
// biz property.
Property *Property
// redis
Redis *Redis
// databus
DBScoreChange *databus.Config
// qcloud
Qcloud *Qcloud
// bm
BM *bm.ServerConfig
// grpc
GRPC *warden.ServerConfig
}
// DB config.
type DB struct {
Spy *sql.Config
}
// Redis redis.
type Redis struct {
*redis.Config
Expire xtime.Duration
VerifyCdTimes xtime.Duration
}
// RPC clients config.
type RPC struct {
Account *rpc.ClientConfig
}
// Memcache config.
type Memcache struct {
User *memcache.Config
UserExpire time.Duration
}
// Property config for biz logic.
type Property struct {
TelValidateURL string
BlockAccountURL string
SecurityLoginURL string
TelInfoByMidURL string
ProfileInfoByMidURL string
UnicomGiftStateURL string
LoadEventTick xtime.Duration
DoubleCheckLevel int32
ConfigLoadTick xtime.Duration
UserInfoShard int64
HistoryShard int64
AutoBlockSwitch bool
Score *struct {
BaseInit int8
EventInit int8
}
Punishment *struct {
ScoreThreshold int8
Times int8
}
Event *struct {
ServiceName string
InitEventID int64
BindMailAndTelLowRisk string
BindMailOnly string
BindNothing string
BindTelLowRiskOnly string
BindTelMediumRisk string
BindTelHighRisk string
BindTelUnknownRisk string
BindTelLowRiskAndIdenAuth string
BindTelLowRiskAndIdenUnauth string
BindTelUnknownRiskAndIdenAuth string
BindTelMediumRiskAndIdenAuth string
BindTelUnknownRiskAndIdenUnauth string
BindTelMediumRiskAndIdenUnauth string
BindMailAndIdenUnknown string
BindTelHighRiskAndIdenAuth string
BindNothingV2 string
BindNothingAndIdenAuth string
BindTelHighRiskAndIdenUnauth string
}
Block *struct {
CycleTimes int64 // unit per seconds
}
White *struct {
Tels []struct {
From int64 // <= from
To int64 // >= to
}
}
}
// Qcloud def.
type Qcloud struct {
Path string
Region string
SecretID string
SecretKey string
Charset string
BaseURL string
}
func init() {
flag.StringVar(&confPath, "conf", "", "config path")
}
// Init init conf.
func Init() (err error) {
if confPath == "" {
return configCenter()
}
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func configCenter() (err error) {
if client, err = conf.New(); err != nil {
panic(err)
}
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,27 @@
package conf
import (
"flag"
"testing"
)
func TestInit(t *testing.T) {
flag.Set("conf", "../cmd/spy-service-test.toml")
flag.Parse()
var err error
if err = Init(); err != nil {
t.Fatal(err)
}
if Conf == nil {
t.Fatal()
}
if Conf.Property.Punishment == nil {
t.Fatal()
}
if Conf.Property.Score == nil {
t.Fatal()
}
t.Log(Conf.Property.AutoBlockSwitch)
t.Log(Conf.Property.White.Tels)
}

View File

@ -0,0 +1,74 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"account_test.go",
"audit_test.go",
"bilibili_card_test.go",
"dao_test.go",
"databus_test.go",
"memcache_test.go",
"mysql_test.go",
"qcloud_test.go",
"redis_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/spy/conf:go_default_library",
"//app/service/main/spy/model:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"audit.go",
"bilibili_card.go",
"dao.go",
"databus.go",
"memcache.go",
"mysql.go",
"qcloud.go",
"redis.go",
],
importpath = "go-common/app/service/main/spy/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/spy/conf:go_default_library",
"//app/service/main/spy/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/queue/databus: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,132 @@
package dao
import (
"context"
"fmt"
"net/url"
"go-common/app/service/main/spy/model"
"go-common/library/log"
)
// tel level.
const (
TelRiskLevelLow = 1
TelRiskLevelMedium = 2
TelRiskLevelHigh = 3
TelRiskLevelUnknown = 4
)
// TelRiskLevel tel risk level.
func (d *Dao) TelRiskLevel(c context.Context, mid int64) (riskLevel int8, err error) {
params := url.Values{}
params.Set("mid", fmt.Sprintf("%d", mid))
params.Set("type", "123")
var resp struct {
TS int64 `json:"ts"`
Code int64 `json:"code"`
Data struct {
Level int8 `json:"level"`
Mid int64 `json:"mid"`
Score int64 `json:"score"`
} `json:"data"`
}
if err = d.httpClient.Get(c, d.c.Property.TelValidateURL, "", params, &resp); err != nil {
log.Error("d.httpClient.Do() error(%v) , riskLevel = TelRiskLevelUnknown", err)
riskLevel = TelRiskLevelUnknown
err = nil
return
}
if resp.Code != 0 {
err = fmt.Errorf("GET TelRiskLevel url resp(%v)", resp)
return
}
log.Info("GET TelValidateURL suc url(%s) resp(%v)", d.c.Property.TelValidateURL+"?"+params.Encode(), resp)
riskLevel = resp.Data.Level
return
}
// BlockAccount block account.
func (d *Dao) BlockAccount(c context.Context, mid int64) (err error) {
params := url.Values{}
params.Set("mid", fmt.Sprintf("%d", mid))
params.Set("admin_reason", "spy")
params.Set("blockType", "3")
params.Set("operator", "spy")
params.Set("type", "json")
var resp struct {
Code int64 `json:"code"`
}
if err = d.httpClient.Get(c, d.c.Property.BlockAccountURL, "", params, &resp); err != nil {
log.Error("httpClient.Do() error(%v)", err)
return
}
if resp.Code != 0 {
err = fmt.Errorf("GET block account url resp(%v)", resp)
}
return
}
// SecurityLogin security login
func (d *Dao) SecurityLogin(c context.Context, mid int64, reason string) (err error) {
params := url.Values{}
params.Set("mids", fmt.Sprintf("%d", mid))
params.Set("operator", "spy")
params.Set("desc", reason)
params.Set("type", "json")
var resp struct {
Code int64 `json:"code"`
}
if err = d.httpClient.Post(c, d.c.Property.SecurityLoginURL, "", params, &resp); err != nil {
log.Error("message url(%s) error(%v)", d.c.Property.SecurityLoginURL+"?"+params.Encode(), err)
return
}
if resp.Code != 0 {
err = fmt.Errorf("POST SecurityLogin url resp(%v)", resp)
return
}
log.Info("POST SecurityLogin suc url(%s) resp(%v)", resp)
return
}
// TelInfo tel info.
func (d *Dao) TelInfo(c context.Context, mid int64) (tel *model.TelInfo, err error) {
params := url.Values{}
params.Set("mid", fmt.Sprintf("%d", mid))
var resp struct {
Code int64 `json:"code"`
Data model.TelInfo `json:"data"`
}
if err = d.httpClient.Get(c, d.c.Property.TelInfoByMidURL, "", params, &resp); err != nil {
log.Error("d.httpClient.Do() error(%v) ,TelInfo", err)
return
}
if resp.Code != 0 {
err = fmt.Errorf("GET TelRiskLevel url resp(%v)", resp)
return
}
tel = &resp.Data
log.Info("GET TelInfoByMidURL suc url(%s) resp(%v)", d.c.Property.TelInfoByMidURL+"?"+params.Encode(), resp)
return
}
// ProfileInfo get user profile info from account service.
func (d *Dao) ProfileInfo(c context.Context, mid int64, remoteIP string) (profile *model.ProfileInfo, err error) {
params := url.Values{}
params.Set("mid", fmt.Sprintf("%d", mid))
var resp struct {
Code int64 `json:"code"`
Data model.ProfileInfo `json:"data"`
}
if err = d.httpClient.Get(c, d.c.Property.ProfileInfoByMidURL, remoteIP, params, &resp); err != nil {
log.Error("d.httpClient.Do() error(%v), ProfileInfo", err)
return
}
if resp.Code != 0 {
err = fmt.Errorf("GET ProfileInfo url resp(%v)", resp)
return
}
profile = &resp.Data
log.Info("GET ProfileInfoByMidURL suc url(%s) resp(%v)", d.c.Property.ProfileInfoByMidURL+"?"+params.Encode(), resp)
return
}

View File

@ -0,0 +1,87 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoTelRiskLevel(t *testing.T) {
convey.Convey("TelRiskLevel", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
riskLevel, err := d.TelRiskLevel(c, mid)
ctx.Convey("Then err should be nil.riskLevel should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(riskLevel, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoBlockAccount(t *testing.T) {
convey.Convey("BlockAccount", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.BlockAccount(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoSecurityLogin(t *testing.T) {
convey.Convey("SecurityLogin", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
reason = "unit test"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.SecurityLogin(c, mid, reason)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoTelInfo(t *testing.T) {
convey.Convey("TelInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tel, err := d.TelInfo(c, mid)
ctx.Convey("Then err should be nil.tel should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(tel, convey.ShouldNotBeNil)
})
})
})
}
func TestProfileInfo(t *testing.T) {
convey.Convey("ProfileInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tel, err := d.ProfileInfo(c, mid, "")
ctx.Convey("Then err should be nil.tel should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(tel, convey.ShouldNotBeNil)
})
})
})
}

View File

@ -0,0 +1,37 @@
package dao
import (
"context"
"net/url"
"strconv"
"go-common/app/service/main/spy/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_auditInfo = "/api/member/audit"
)
// AuditInfo get user audit info
func (d *Dao) AuditInfo(c context.Context, mid int64, remoteIP string) (rs *model.AuditInfo, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data model.AuditInfo `json:"data"`
}
if err = d.httpClient.Get(c, d.auditInfoURI, remoteIP, params, &res); err != nil {
log.Error("account get audit info url(%s) error(%v)", d.auditInfoURI+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
log.Error("account get audit info url(%s) error(%v)", d.auditInfoURI+"?"+params.Encode(), res.Code)
err = ecode.Int(res.Code)
return
}
rs = &res.Data
log.Info("GET AuditInfoURL suc url(%s) resp(%v)", d.auditInfoURI+"?"+params.Encode(), res)
return
}

View File

@ -0,0 +1,24 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoAuditInfo(t *testing.T) {
convey.Convey("AuditInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
remoteIP = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.AuditInfo(c, mid, remoteIP)
ctx.Convey("Then err should be nil.rs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@ -0,0 +1,31 @@
package dao
import (
"context"
"fmt"
"net/url"
"go-common/app/service/main/spy/model"
"go-common/library/log"
)
// UnicomGiftState get unicom gift state by mid from account service.
func (d *Dao) UnicomGiftState(c context.Context, mid int64) (state int, err error) {
params := url.Values{}
params.Set("mid", fmt.Sprintf("%d", mid))
var resp struct {
Code int64 `json:"code"`
Data *model.UnicomGiftState `json:"data"`
}
if err = d.httpClient.Get(c, d.c.Property.UnicomGiftStateURL, "", params, &resp); err != nil {
log.Error("message url(%s) error(%v)", d.c.Property.UnicomGiftStateURL+"?"+params.Encode(), err)
return
}
if resp.Code != 0 {
err = fmt.Errorf("GET UnicomGiftStateURL url resp(%v)", resp)
return
}
log.Info("GET UnicomGiftStateURL suc url(%s) resp(%v)", d.c.Property.UnicomGiftStateURL+"?"+params.Encode(), resp)
state = resp.Data.State
return
}

View File

@ -0,0 +1,24 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoUnicomGiftState(t *testing.T) {
convey.Convey("UnicomGiftState", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(27515247)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
state, err := d.UnicomGiftState(c, mid)
ctx.Convey("Then err should be nil.state should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(state, convey.ShouldNotBeNil)
})
})
})
}

View File

@ -0,0 +1,87 @@
package dao
import (
"context"
"math/rand"
"time"
"go-common/app/service/main/spy/conf"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/database/sql"
bm "go-common/library/net/http/blademaster"
"go-common/library/queue/databus"
)
// Dao event dao def.
type Dao struct {
c *conf.Config
// db
db *sql.DB
// mc
mcUser *memcache.Pool
mcUserExpire int32
// redis
redis *redis.Pool
expire int
verifyExpire int
// http client
httpClient *bm.Client
auditInfoURI string
// databus for spy score change
dbScoreChange *databus.Databus
r *rand.Rand
}
// New create instance of dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
// db
db: sql.NewMySQL(c.DB.Spy),
// mc
mcUser: memcache.NewPool(c.Memcache.User),
mcUserExpire: int32(time.Duration(c.Memcache.UserExpire) / time.Second),
// redis
redis: redis.NewPool(c.Redis.Config),
expire: int(time.Duration(c.Redis.Expire) / time.Second),
verifyExpire: int(time.Duration(c.Redis.VerifyCdTimes) / time.Second),
// http client
httpClient: bm.NewClient(c.HTTPClient),
auditInfoURI: c.Account + _auditInfo,
// databus
dbScoreChange: databus.New(c.DBScoreChange),
r: rand.New(rand.NewSource(time.Now().Unix())),
}
if conf.Conf.Property.UserInfoShard <= 0 {
panic("conf.Conf.Property.UserInfoShard <= 0")
}
if conf.Conf.Property.HistoryShard <= 0 {
panic("conf.Conf.Property.HistoryShard <= 0")
}
return
}
// Ping check db health.
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.pingMC(c); err != nil {
return
}
if err = d.PingRedis(c); err != nil {
return
}
return d.db.Ping(c)
}
// Close close all db connections.
func (d *Dao) Close() {
if d.mcUser != nil {
d.mcUser.Close()
}
if d.redis != nil {
d.redis.Close()
}
if d.db != nil {
d.db.Close()
}
}

View File

@ -0,0 +1,35 @@
package dao
import (
"flag"
"go-common/app/service/main/spy/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.account.spy-service")
flag.Set("conf_token", "22741f7d4338595a152f282062e4e2fa")
flag.Set("tree_id", "2855")
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/spy-service.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

View File

@ -0,0 +1,17 @@
package dao
import (
"context"
"strconv"
"go-common/library/log"
)
// PubScoreChange pub spy score change msg into databus.
func (d *Dao) PubScoreChange(c context.Context, mid int64, msg interface{}) (err error) {
key := strconv.FormatInt(mid, 10)
if err = d.dbScoreChange.Send(c, key, msg); err != nil {
log.Error("d.dbScoreChange.Send(%s, %v) error (%v)", key, msg, err)
}
return
}

View File

@ -0,0 +1,24 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoPubScoreChange(t *testing.T) {
convey.Convey("PubScoreChange", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
msg = interface{}(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.PubScoreChange(c, mid, msg)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@ -0,0 +1,103 @@
package dao
import (
"context"
"fmt"
"go-common/app/service/main/spy/model"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_userKey = "u_%d"
)
// pingMC ping memcache.
func (d *Dao) pingMC(c context.Context) (err error) {
conn := d.mcUser.Get(c)
defer conn.Close()
if err = conn.Set(&memcache.Item{Key: "ping", Value: []byte{1}, Expiration: 0}); err != nil {
log.Error("conn.Store(set,ping,1) error(%v)", err)
}
return
}
func userInfoCacheKey(mid int64) string {
return fmt.Sprintf(_userKey, mid)
}
// UserInfoCache get user info to cache.
func (d *Dao) UserInfoCache(c context.Context, mid int64) (ui *model.UserInfo, err error) {
var (
key = userInfoCacheKey(mid)
conn = d.mcUser.Get(c)
)
defer conn.Close()
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("conn.Get(get, %s) error(%v)", key, err)
return
}
ui = &model.UserInfo{}
if err = conn.Scan(reply, ui); err != nil {
log.Error("reply.Scan(%s) error(%v)", string(reply.Value), err)
}
return
}
// AddUserInfoCache add info to cache , return err if key is exist already.
func (d *Dao) AddUserInfoCache(c context.Context, ui *model.UserInfo) (err error) {
if ui == nil {
return fmt.Errorf("AddUserInfoCache got nil *model.UserInfo")
}
var (
key = userInfoCacheKey(ui.Mid)
conn = d.mcUser.Get(c)
)
defer conn.Close()
if err = conn.Add(&memcache.Item{Key: key, Object: ui, Expiration: d.mcUserExpire, Flags: memcache.FlagJSON}); err != nil {
log.Error("conn.Add(%s, %v) error(%v)", key, ui, err)
return
}
return
}
// SetUserInfoCache set info cache.
func (d *Dao) SetUserInfoCache(c context.Context, ui *model.UserInfo) (err error) {
if ui == nil {
return fmt.Errorf("SetUserInfoCache got nil *model.UserInfo")
}
var (
key = userInfoCacheKey(ui.Mid)
conn = d.mcUser.Get(c)
)
defer conn.Close()
if err = conn.Set(&memcache.Item{Key: key, Object: ui, Expiration: d.mcUserExpire, Flags: memcache.FlagJSON}); err != nil {
log.Error("conn.Set(%s, %v) error(%v)", key, ui, err)
}
return
}
// DelInfoCache delete info cache.
func (d *Dao) DelInfoCache(c context.Context, mid int64) (err error) {
var (
key = userInfoCacheKey(mid)
conn = d.mcUser.Get(c)
)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("conn.Delete(%s) error(%v)", key, err)
}
return
}

View File

@ -0,0 +1,97 @@
package dao
import (
"context"
"go-common/app/service/main/spy/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaopingMC(t *testing.T) {
convey.Convey("pingMC", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.pingMC(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaouserInfoCacheKey(t *testing.T) {
convey.Convey("userInfoCacheKey", t, func(ctx convey.C) {
var (
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := userInfoCacheKey(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUserInfoCache(t *testing.T) {
convey.Convey("UserInfoCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.UserInfoCache(c, mid)
ctx.Convey("Then err should be nil.ui should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoAddUserInfoCache(t *testing.T) {
convey.Convey("AddUserInfoCache", t, func(ctx convey.C) {
var (
c = context.Background()
ui = &model.UserInfo{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AddUserInfoCache(c, ui)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSetUserInfoCache(t *testing.T) {
convey.Convey("SetUserInfoCache", t, func(ctx convey.C) {
var (
c = context.Background()
ui = &model.UserInfo{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.SetUserInfoCache(c, ui)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoDelInfoCache(t *testing.T) {
convey.Convey("DelInfoCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DelInfoCache(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@ -0,0 +1,475 @@
package dao
import (
"context"
xsql "database/sql"
"fmt"
"time"
"go-common/app/service/main/spy/conf"
"go-common/app/service/main/spy/model"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_serviceSQL = "SELECT id,name,nick_name,status,ctime,mtime FROM spy_service WHERE name=? AND status<>0 LIMIT 1"
_addServiceSQL = "INSERT INTO spy_service (name,nick_name,status,ctime) VALUES (?,?,?,?)"
_eventSQL = "SELECT id,name,nick_name,service_id,status,ctime,mtime FROM spy_event WHERE name=? AND status<>0 LIMIT 1"
_addEventSQL = "INSERT INTO spy_event (name,nick_name,service_id,status,ctime) VALUES (?,?,?,?,?)"
_factorSQL = "SELECT id,nick_name,service_id,event_id,group_id,risk_level,factor_val,ctime,mtime FROM spy_factor WHERE service_id=? AND event_id=? AND risk_level=? LIMIT 1"
_factorGroupSQL = "SELECT id,name,ctime FROM spy_factor_group WHERE name=? LIMIT 1"
_userInfoSQL = "SELECT id,mid,score,base_score,event_score,state,relive_times,ctime,mtime FROM spy_user_info_%02d WHERE mid=? LIMIT 1"
_addUserInfoSQL = "INSERT IGNORE INTO spy_user_info_%02d (mid,score,base_score,event_score,state,ctime,mtime) VALUES (?,?,?,?,?,?,?)"
_updateEventScoreSQL = "UPDATE spy_user_info_%02d SET event_score=?, score=? WHERE mid=?"
_updateInfoSQL = "UPDATE spy_user_info_%02d SET base_score=?, event_score=?, score=?, state=? WHERE mid=?;"
_updateBaseScoreSQL = "UPDATE spy_user_info_%02d SET base_score=?, score=? WHERE mid=?;"
_addEventHistorySQL = "INSERT INTO spy_user_event_history_%02d (mid,event_id,score,base_score,event_score,remark,reason,factor_val,ctime) VALUES (?,?,?,?,?,?,?,?,?);"
_getEventHistoryByMidAndEventSQL = "SELECT mid, event_id FROM spy_user_event_history_%02d WHERE mid = ? and event_id = ? limit 1"
_addPunishmentSQL = "INSERT INTO spy_punishment (mid,type,reason,ctime) VALUES (?,?,?,?);"
_addPunishmentQueueSQL = "INSERT INTO spy_punishment_queue (mid,batch_no,ctime) VALUES (?,?,?) ON DUPLICATE KEY UPDATE mtime=?;"
_getAllConfigSQL = "SELECT id, property,name,val,ctime FROM spy_system_config;"
_clearReliveTimesSQL = "UPDATE spy_user_info_%02d SET relive_times=? WHERE mid=?;"
_getHistoryListSQL = "SELECT remark,reason FROM spy_user_event_history_%02d WHERE mid= ? ORDER BY id DESC LIMIT ?;"
_updateEventScoreReLiveSQL = "UPDATE spy_user_info_%02d SET event_score=?, score=?, relive_times=relive_times+1 WHERE mid=?"
_statListByMidSQL = "SELECT event_id,quantity FROM spy_statistics WHERE target_mid = ? AND isdel = 0 ORDER BY id desc LIMIT 100;"
_statListByIDSQL = "SELECT event_id,quantity FROM spy_statistics WHERE target_id = ? AND isdel = 0 ORDER BY id desc LIMIT 100;"
_statListByIDAndMidSQL = "SELECT event_id,quantity FROM spy_statistics WHERE target_mid = ? AND target_id = ? AND isdel = 0 ORDER BY id desc LIMIT 100;"
_allEventSQL = "SELECT id,name,nick_name,service_id,status,ctime,mtime FROM spy_event WHERE status<>0"
_telLevelSQL = "SELECT id,mid,level,origin,ctime,mtime FROM spy_tel_risk_level WHERE mid = ? LIMIT 1;"
_addTelLevelSQL = "INSERT INTO spy_tel_risk_level (mid,level,origin,ctime) VALUES (?,?,?,?) "
)
// Service get service from db.
func (d *Dao) Service(c context.Context, serviceName string) (service *model.Service, err error) {
var (
row *sql.Row
)
service = &model.Service{}
row = d.db.QueryRow(c, _serviceSQL, serviceName)
if err = row.Scan(&service.ID, &service.Name, &service.NickName, &service.Status, &service.CTime, &service.MTime); err != nil {
if err == sql.ErrNoRows {
err = nil
service = nil
return
}
log.Error("row.Scan() error(%v)", err)
}
return
}
// Event get event from db.
func (d *Dao) Event(c context.Context, eventName string) (event *model.Event, err error) {
var row *sql.Row
event = &model.Event{}
row = d.db.QueryRow(c, _eventSQL, eventName)
if err = row.Scan(&event.ID, &event.Name, &event.NickName, &event.ServiceID, &event.Status, &event.CTime, &event.MTime); err != nil {
if err == sql.ErrNoRows {
err = nil
event = nil
return
}
log.Error("row.Scan() error(%v)", err)
}
return
}
// AddService insert service to db.
func (d *Dao) AddService(c context.Context, service *model.Service) (id int64, err error) {
var (
res xsql.Result
)
if res, err = d.db.Exec(c, _addServiceSQL, service.Name, service.NickName, service.Status, time.Now()); err != nil {
log.Error("d.db.Exec(%s, %s, %d) error(%v)", _addServiceSQL, service.Name, service.Status, err)
return
}
if id, err = res.LastInsertId(); err != nil {
log.Error("res.LastInsertId() error(%v)", err)
}
return
}
// AddEvent insert service to db.
func (d *Dao) AddEvent(c context.Context, event *model.Event) (id int64, err error) {
var (
res xsql.Result
)
if res, err = d.db.Exec(c, _addEventSQL, event.Name, event.NickName, event.ServiceID, event.Status, time.Now()); err != nil {
log.Error("d.db.Exec(%s, %s, %s, %d, %d) error(%v)", _addEventSQL, event.Name, event.NickName, event.ServiceID, event.Status, err)
return
}
if id, err = res.LastInsertId(); err != nil {
log.Error("res.LastInsertId() error(%v)", err)
}
return
}
// Factor get factor from db.
func (d *Dao) Factor(c context.Context, serviceID, eventID int64, riskLevel int8) (factor *model.Factor, err error) {
var (
row *sql.Row
)
factor = &model.Factor{}
row = d.db.QueryRow(c, _factorSQL, serviceID, eventID, riskLevel)
if err = row.Scan(&factor.ID, &factor.NickName, &factor.ServiceID, &factor.EventID, &factor.GroupID, &factor.RiskLevel, &factor.FactorVal, &factor.CTime, &factor.MTime); err != nil {
if err == sql.ErrNoRows {
err = nil
factor = nil
return
}
log.Error("row.Scan() error(%v)", err)
}
return
}
// FactorGroup get factor group from db.
func (d *Dao) FactorGroup(c context.Context, groupName string) (factorGroup *model.FactorGroup, err error) {
var (
row *sql.Row
)
factorGroup = &model.FactorGroup{}
row = d.db.QueryRow(c, _factorGroupSQL, groupName)
if err = row.Scan(&factorGroup.ID, &factorGroup.Name, &factorGroup.CTime); err != nil {
if err == sql.ErrNoRows {
err = nil
factorGroup = nil
return
}
log.Error("row.Scan() error(%v)", err)
}
return
}
func hitInfo(id int64) int64 {
return id % conf.Conf.Property.UserInfoShard
}
func hitHistory(id int64) int64 {
return id % conf.Conf.Property.HistoryShard
}
// BeginTran begin transaction.
func (d *Dao) BeginTran(c context.Context) (*sql.Tx, error) {
return d.db.Begin(c)
}
// UserInfo get info by mid.
func (d *Dao) UserInfo(c context.Context, mid int64) (res *model.UserInfo, err error) {
var (
row *sql.Row
)
res = &model.UserInfo{}
row = d.db.QueryRow(c, fmt.Sprintf(_userInfoSQL, hitInfo(mid)), mid)
if err = row.Scan(&res.ID, &res.Mid, &res.Score, &res.BaseScore, &res.EventScore, &res.State, &res.ReliveTimes, &res.CTime, &res.MTime); err != nil {
if err == sql.ErrNoRows {
err = nil
res = nil
return
}
log.Error("row.Scan() error(%v)", err)
}
return
}
// TxUpdateInfo insert or update user info by mid.
func (d *Dao) TxUpdateInfo(c context.Context, tx *sql.Tx, info *model.UserInfo) (err error) {
if _, err = d.db.Exec(c, fmt.Sprintf(_updateInfoSQL, hitInfo(info.Mid)), info.BaseScore, info.EventScore, info.Score, info.State, info.Mid); err != nil {
log.Error("db.Exec(%d, %+v) error(%v)", info.Mid, info, err)
return
}
return
}
// TxAddInfo add user info.
func (d *Dao) TxAddInfo(c context.Context, tx *sql.Tx, info *model.UserInfo) (id int64, err error) {
var (
res xsql.Result
now = time.Now()
)
if res, err = tx.Exec(fmt.Sprintf(_addUserInfoSQL, hitInfo(info.Mid)), info.Mid, info.Score, info.BaseScore, info.EventScore, info.State, now, now); err != nil {
log.Error("db.Exec(%d, %v) error(%v)", info.Mid, *info, err)
return
}
return res.LastInsertId()
}
// TxAddEventHistory insert user_event_history.
func (d *Dao) TxAddEventHistory(c context.Context, tx *sql.Tx, ueh *model.UserEventHistory) (err error) {
var (
now = time.Now()
)
if _, err = tx.Exec(fmt.Sprintf(_addEventHistorySQL, hitHistory(ueh.Mid)), ueh.Mid, ueh.EventID, ueh.Score, ueh.BaseScore, ueh.EventScore, ueh.Remark, ueh.Reason, ueh.FactorVal, now); err != nil {
log.Error("db.Exec(%v) error(%v)", ueh, err)
return
}
return
}
// EventHistoryByMidAndEvent get one event history with mid and eventID from db.
func (d *Dao) EventHistoryByMidAndEvent(c context.Context, mid int64, eventID int64) (res *model.UserEventHistory, err error) {
var (
row *sql.Row
)
res = &model.UserEventHistory{}
row = d.db.QueryRow(c, fmt.Sprintf(_getEventHistoryByMidAndEventSQL, hitHistory(mid)), mid, eventID)
if err = row.Scan(&res.Mid, &res.EventID); err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
log.Error("row.Scan() error:(%v)", err)
}
return
}
// TxAddPunishment insert punishment.
func (d *Dao) TxAddPunishment(c context.Context, tx *sql.Tx, mid int64, t int8, reason string) (err error) {
var (
now = time.Now()
)
if _, err = tx.Exec(_addPunishmentSQL, mid, t, reason, now); err != nil {
log.Error("db.Exec(%d, %d, %s) error(%v)", mid, t, reason, err)
return
}
return
}
// TxAddPunishmentQueue insert punishment queue.
func (d *Dao) TxAddPunishmentQueue(c context.Context, tx *sql.Tx, mid int64, blockNo int64) (err error) {
var (
now = time.Now()
)
if _, err = tx.Exec(_addPunishmentQueueSQL, mid, blockNo, now, now); err != nil {
log.Error("TxAddPunishmentQueue:db.Exec(%d) error(%v)", mid, err)
return
}
return
}
// AddPunishmentQueue insert punishment queue.
func (d *Dao) AddPunishmentQueue(c context.Context, mid int64, blockNo int64) (err error) {
var (
now = time.Now()
)
if _, err = d.db.Exec(c, _addPunishmentQueueSQL, mid, blockNo, now, now); err != nil {
log.Error("AddPunishmentQueue:db.Exec(%d) error(%v)", mid, err)
return
}
return
}
// TxUpdateEventScore update user event score.
func (d *Dao) TxUpdateEventScore(c context.Context, tx *sql.Tx, mid int64, escore, score int8) (err error) {
if _, err = tx.Exec(fmt.Sprintf(_updateEventScoreSQL, hitInfo(mid)), escore, score, mid); err != nil {
log.Error("db.TxUpdateEventScore(%s, %d, %d, %d) error(%v)", _updateEventScoreSQL, escore, score, mid, err)
return
}
return
}
//TxUpdateBaseScore do update user base score.
func (d *Dao) TxUpdateBaseScore(c context.Context, tx *sql.Tx, ui *model.UserInfo) (err error) {
if _, err = tx.Exec(fmt.Sprintf(_updateBaseScoreSQL, hitInfo(ui.Mid)), ui.BaseScore, ui.Score, ui.Mid); err != nil {
log.Error("db.TxUpdateBaseScore(%d, %d, %d) error(%v)", ui.BaseScore, ui.Score, ui.Mid, err)
return
}
return
}
//TxClearReliveTimes do clear user relivetimes.
func (d *Dao) TxClearReliveTimes(c context.Context, tx *sql.Tx, ui *model.UserInfo) (err error) {
if _, err = tx.Exec(fmt.Sprintf(_clearReliveTimesSQL, hitInfo(ui.Mid)), ui.ReliveTimes, ui.Mid); err != nil {
log.Error("db.TxClearReliveTimes(%d, %d) error(%v)", ui.ReliveTimes, ui.Mid, err)
return
}
return
}
// Configs spy system configs.
func (d *Dao) Configs(c context.Context) (res map[string]string, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, _getAllConfigSQL); err != nil {
log.Error("d.getAllConfigSQL.Query error(%v)", err)
return
}
defer rows.Close()
res = make(map[string]string)
for rows.Next() {
var r model.Config
if err = rows.Scan(&r.ID, &r.Property, &r.Name, &r.Val, &r.Ctime); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res[r.Property] = r.Val
}
err = rows.Err()
return
}
// HistoryList query .
func (d *Dao) HistoryList(c context.Context, mid int64, size int) (res []*model.UserEventHistory, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, fmt.Sprintf(_getHistoryListSQL, hitHistory(mid)), mid, size); err != nil {
log.Error("d.HistoryList.Query(%d, %d) error(%v)", mid, size, err)
return
}
defer rows.Close()
for rows.Next() {
r := &model.UserEventHistory{}
if err = rows.Scan(&r.Remark, &r.Reason); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
err = rows.Err()
return
}
// TxUpdateEventScoreReLive update event score and times
func (d *Dao) TxUpdateEventScoreReLive(c context.Context, tx *sql.Tx, mid int64, escore, score int8) (err error) {
if _, err = tx.Exec(fmt.Sprintf(_updateEventScoreReLiveSQL, hitInfo(mid)), escore, score, mid); err != nil {
log.Error("db.TxUpdateEventScoreReLive(%s, %d, %d, %d) error(%v)", _updateEventScoreReLiveSQL, escore, score, mid, err)
return
}
return
}
//StatListByMid stat list by mid.
func (d *Dao) StatListByMid(c context.Context, mid int64) (list []*model.Statistics, err error) {
var (
rows *sql.Rows
)
list = make([]*model.Statistics, 0)
if rows, err = d.db.Query(c, _statListByMidSQL, mid); err != nil {
log.Error("d.db.Query(%s) error(%v)", _statListByMidSQL, err)
return
}
defer rows.Close()
for rows.Next() {
var r = &model.Statistics{}
if err = rows.Scan(&r.EventID, &r.Quantity); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
list = append(list, &model.Statistics{
EventID: r.EventID,
Quantity: r.Quantity,
})
}
return
}
//StatListByIDAndMid stat list by id.
func (d *Dao) StatListByIDAndMid(c context.Context, mid, id int64) (list []*model.Statistics, err error) {
var (
rows *sql.Rows
)
list = make([]*model.Statistics, 0)
if rows, err = d.db.Query(c, _statListByIDAndMidSQL, mid, id); err != nil {
log.Error("d.db.Query(%s) error(%v)", _statListByIDAndMidSQL, err)
return
}
defer rows.Close()
for rows.Next() {
var r = &model.Statistics{}
if err = rows.Scan(&r.EventID, &r.Quantity); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
list = append(list, &model.Statistics{
EventID: r.EventID,
Quantity: r.Quantity,
})
}
return
}
//StatListByID stat list by id.
func (d *Dao) StatListByID(c context.Context, id int64) (list []*model.Statistics, err error) {
var (
rows *sql.Rows
)
list = make([]*model.Statistics, 0)
if rows, err = d.db.Query(c, _statListByIDSQL, id); err != nil {
log.Error("d.db.Query(%s) error(%v)", _statListByIDSQL, err)
return
}
defer rows.Close()
for rows.Next() {
var r = &model.Statistics{}
if err = rows.Scan(&r.EventID, &r.Quantity); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
list = append(list, &model.Statistics{
EventID: r.EventID,
Quantity: r.Quantity,
})
}
return
}
//AllEvent all event.
func (d *Dao) AllEvent(c context.Context) (list []*model.Event, err error) {
var (
rows *sql.Rows
)
list = make([]*model.Event, 0)
if rows, err = d.db.Query(c, _allEventSQL); err != nil {
log.Error("d.db.Query(%s) error(%v)", _allEventSQL, err)
return
}
defer rows.Close()
for rows.Next() {
var event = &model.Event{}
if err = rows.Scan(&event.ID, &event.Name, &event.NickName, &event.ServiceID, &event.Status, &event.CTime, &event.MTime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
list = append(list, &model.Event{
ID: event.ID,
Name: event.Name,
NickName: event.NickName,
ServiceID: event.ServiceID,
Status: event.Status,
CTime: event.CTime,
MTime: event.MTime,
})
}
return
}
// TelLevel tel level.
func (d *Dao) TelLevel(c context.Context, mid int64) (res *model.TelRiskLevel, err error) {
var (
row *sql.Row
)
res = &model.TelRiskLevel{}
row = d.db.QueryRow(c, _telLevelSQL, mid)
if err = row.Scan(&res.ID, &res.Mid, &res.Level, &res.Origin, &res.Ctime, &res.Mtime); err != nil {
if err == sql.ErrNoRows {
err = nil
res = nil
return
}
log.Error("row.Scan() error(%v)", err)
}
return
}
// AddTelLevelInfo add tel level info.
func (d *Dao) AddTelLevelInfo(c context.Context, t *model.TelRiskLevel) (id int64, err error) {
var (
res xsql.Result
)
if res, err = d.db.Exec(c, _addTelLevelSQL, t.Mid, t.Level, t.Origin, time.Now()); err != nil {
log.Error("d.db.Exec(%s, %v) error(%v)", _addTelLevelSQL, t, err)
return
}
if id, err = res.LastInsertId(); err != nil {
log.Error("res.LastInsertId() error(%v)", err)
}
return
}

View File

@ -0,0 +1,498 @@
package dao
import (
"context"
"fmt"
"testing"
"time"
"go-common/app/service/main/spy/model"
xtime "go-common/library/time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoService(t *testing.T) {
convey.Convey("Service", t, func(ctx convey.C) {
var (
c = context.Background()
serviceName = "account-service"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
service, err := d.Service(c, serviceName)
ctx.Convey("Then err should be nil.service should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(service, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoEvent(t *testing.T) {
convey.Convey("Event", t, func(ctx convey.C) {
var (
c = context.Background()
eventName = "init_user_info"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.Event(c, eventName)
ctx.Convey("Then err should be nil.event should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoAddService(t *testing.T) {
convey.Convey("AddService", t, func(ctx convey.C) {
var (
c = context.Background()
service = &model.Service{
Name: fmt.Sprintf("ut_%d", time.Now().Unix()),
NickName: "test",
Status: 0,
CTime: xtime.Time(time.Now().Unix()),
MTime: xtime.Time(time.Now().Unix()),
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
id, err := d.AddService(c, service)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddEvent(t *testing.T) {
convey.Convey("AddEvent", t, func(ctx convey.C) {
var (
c = context.Background()
event = &model.Event{
Name: fmt.Sprintf("ut_%d", time.Now().Unix()),
NickName: "test",
Status: 1,
CTime: xtime.Time(time.Now().Unix()),
MTime: xtime.Time(time.Now().Unix()),
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
id, err := d.AddEvent(c, event)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoFactor(t *testing.T) {
convey.Convey("Factor", t, func(ctx convey.C) {
var (
c = context.Background()
serviceID = int64(1)
eventID = int64(1)
riskLevel = int8(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
factor, err := d.Factor(c, serviceID, eventID, riskLevel)
ctx.Convey("Then err should be nil.factor should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(factor, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoFactorGroup(t *testing.T) {
convey.Convey("FactorGroup", t, func(ctx convey.C) {
var (
c = context.Background()
groupName = "基础资料分值"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.FactorGroup(c, groupName)
ctx.Convey("Then err should be nil.factorGroup should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaohitInfo(t *testing.T) {
convey.Convey("hitInfo", t, func(ctx convey.C) {
var (
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := hitInfo(id)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaohitHistory(t *testing.T) {
convey.Convey("hitHistory", t, func(ctx convey.C) {
var (
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := hitHistory(id)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoBeginTran(t *testing.T) {
convey.Convey("BeginTran", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1, err := d.BeginTran(c)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUserInfo(t *testing.T) {
convey.Convey("UserInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.UserInfo(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 TestDaoTxUpdateInfo(t *testing.T) {
convey.Convey("TxUpdateInfo", t, func(ctx convey.C) {
var (
c = context.Background()
info = &model.UserInfo{
Mid: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
err = d.TxUpdateInfo(c, tx, info)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoTxAddInfo(t *testing.T) {
convey.Convey("TxAddInfo", t, func(ctx convey.C) {
var (
c = context.Background()
info = &model.UserInfo{
Mid: time.Now().Unix(),
}
id int64
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
id, err = d.TxAddInfo(c, tx, info)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoTxAddEventHistory(t *testing.T) {
convey.Convey("TxAddEventHistory", t, func(ctx convey.C) {
var (
c = context.Background()
ueh = &model.UserEventHistory{
Mid: 1,
Remark: "un_test",
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
err = d.TxAddEventHistory(c, tx, ueh)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoTxAddPunishment(t *testing.T) {
convey.Convey("TxAddPunishment", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
no = int8(0)
reason = "unit test"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
err = d.TxAddPunishment(c, tx, mid, no, reason)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoTxAddPunishmentQueue(t *testing.T) {
convey.Convey("TxAddPunishmentQueue", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
blockNo = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
err = d.TxAddPunishmentQueue(c, tx, mid, blockNo)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoAddPunishmentQueue(t *testing.T) {
convey.Convey("AddPunishmentQueue", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
blockNo = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AddPunishmentQueue(c, mid, blockNo)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoTxUpdateEventScore(t *testing.T) {
convey.Convey("TxUpdateEventScore", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
escore = int8(0)
score = int8(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
err = d.TxUpdateEventScore(c, tx, mid, escore, score)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoTxUpdateBaseScore(t *testing.T) {
convey.Convey("TxUpdateBaseScore", t, func(ctx convey.C) {
var (
c = context.Background()
ui = &model.UserInfo{Mid: 1}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
err = d.TxUpdateBaseScore(c, tx, ui)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoTxClearReliveTimes(t *testing.T) {
convey.Convey("TxClearReliveTimes", t, func(ctx convey.C) {
var (
c = context.Background()
ui = &model.UserInfo{Mid: 1}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
err = d.TxClearReliveTimes(c, tx, ui)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoConfigs(t *testing.T) {
convey.Convey("Configs", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.Configs(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 TestDaoHistoryList(t *testing.T) {
convey.Convey("HistoryList", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
size = int(10)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.HistoryList(c, mid, size)
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 TestDaoTxUpdateEventScoreReLive(t *testing.T) {
convey.Convey("TxUpdateEventScoreReLive", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
escore = int8(0)
score = int8(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
err = d.TxUpdateEventScoreReLive(c, tx, mid, escore, score)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoStatListByMid(t *testing.T) {
convey.Convey("StatListByMid", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
list, err := d.StatListByMid(c, mid)
ctx.Convey("Then err should be nil.list should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(list, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoStatListByIDAndMid(t *testing.T) {
convey.Convey("StatListByIDAndMid", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
list, err := d.StatListByIDAndMid(c, mid, id)
ctx.Convey("Then err should be nil.list should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(list, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoStatListByID(t *testing.T) {
convey.Convey("StatListByID", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
list, err := d.StatListByID(c, id)
ctx.Convey("Then err should be nil.list should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(list, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAllEvent(t *testing.T) {
convey.Convey("AllEvent", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
list, err := d.AllEvent(c)
ctx.Convey("Then err should be nil.list should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(list, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoTelLevel(t *testing.T) {
convey.Convey("TelLevel", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.TelLevel(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoAddTelLevelInfo(t *testing.T) {
convey.Convey("AddTelLevelInfo", t, func(ctx convey.C) {
var (
c = context.Background()
no = &model.TelRiskLevel{
Mid: time.Now().Unix(),
Level: 1,
Origin: 1,
Ctime: time.Now(),
Mtime: time.Now(),
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
id, err := d.AddTelLevelInfo(c, no)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}

View File

@ -0,0 +1,85 @@
package dao
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"net/http"
"net/url"
"sort"
"time"
"go-common/app/service/main/spy/model"
"go-common/library/log"
)
func (d *Dao) hmacsha1(key, text string) (h string) {
mac := hmac.New(sha1.New, []byte(key))
mac.Write([]byte(text))
h = base64.StdEncoding.EncodeToString(mac.Sum(nil))
return
}
func (d *Dao) makeURL(method string, action string, region string, secretID string, secretKey string,
args url.Values, charset string, URL string) (req string) {
args.Set("Nonce", fmt.Sprintf("%d", d.r.Uint32()))
args.Set("Action", action)
args.Set("Region", region)
args.Set("SecretId", secretID)
args.Set("Timestamp", fmt.Sprintf("%d", time.Now().Unix()))
args.Set("Signature", d.hmacsha1(secretKey, fmt.Sprintf("%s%s?%s", method, URL, d.makeQueryString(args))))
req = args.Encode()
return
}
func (d *Dao) makeQueryString(v url.Values) (str string) {
if v == nil {
return ""
}
var buf bytes.Buffer
keys := make([]string, 0, len(v))
for k := range v {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
vs := v[k]
prefix := k + "="
for _, v := range vs {
if buf.Len() > 0 {
buf.WriteString("&")
}
buf.WriteString(prefix)
buf.WriteString(v)
}
}
return buf.String()
}
// RegisterProtection register protection.
func (d *Dao) RegisterProtection(c context.Context, args url.Values, ip string) (level int8, err error) {
query := d.makeURL("GET", d.c.Qcloud.Path, d.c.Qcloud.Region, d.c.Qcloud.SecretID,
d.c.Qcloud.SecretKey, args, d.c.Qcloud.Charset, d.c.Qcloud.BaseURL)
req, err := http.NewRequest("GET", "https://"+d.c.Qcloud.BaseURL+"?"+query, nil)
if err != nil {
log.Error("d.RegisterProtection uri(%s) error(%v)", query, err)
return
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
res := &model.QcloudRegProResp{}
if err = d.httpClient.Do(c, req, res); err != nil {
log.Error("d.client.Do error(%v) | uri(%s)) res(%v)", err, query, res)
return
}
if res.Code != 0 {
err = fmt.Errorf("GET RegisterProtection req faild query(%s) resp(%v)", d.c.Qcloud.BaseURL+"?"+query, res)
log.Error(" RegisterProtection fail res(%v)", res)
return
}
level = res.Level
log.Info("GET RegisterProtection suc query(%s) resp(%v)", query, res)
return
}

View File

@ -0,0 +1,89 @@
package dao
import (
"context"
"fmt"
"go-common/app/service/main/spy/model"
"net/url"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaohmacsha1(t *testing.T) {
convey.Convey("hmacsha1", t, func(ctx convey.C) {
var (
key = ""
text = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
h := d.hmacsha1(key, text)
ctx.Convey("Then h should not be nil.", func(ctx convey.C) {
ctx.So(h, convey.ShouldNotBeNil)
})
})
})
}
func TestDaomakeURL(t *testing.T) {
convey.Convey("makeURL", t, func(ctx convey.C) {
var (
method = "1"
action = "1"
region = "1"
secretID = "1"
secretKey = "1"
charset = "1"
URL = "1"
)
args := url.Values{}
args.Set("accountType", fmt.Sprintf("%d", model.AccountType))
args.Set("uid", fmt.Sprintf("%d", 1))
args.Set("phoneNumber", "13262609601")
args.Set("registerTime", fmt.Sprintf("%d", time.Now().Unix()))
args.Set("registerIp", "127.0.0.1")
ctx.Convey("When everything goes positive", func(ctx convey.C) {
req := d.makeURL(method, action, region, secretID, secretKey, args, charset, URL)
ctx.Convey("Then req should not be nil.", func(ctx convey.C) {
ctx.So(req, convey.ShouldNotBeNil)
})
})
})
}
func TestDaomakeQueryString(t *testing.T) {
convey.Convey("makeQueryString", t, func(ctx convey.C) {
var (
v url.Values
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
str := d.makeQueryString(v)
ctx.Convey("Then str should not be nil.", func(ctx convey.C) {
ctx.So(str, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoRegisterProtection(t *testing.T) {
convey.Convey("RegisterProtection", t, func(ctx convey.C) {
var (
c = context.Background()
ip = "127.0.0.1"
)
args := url.Values{}
args.Set("accountType", fmt.Sprintf("%d", model.AccountType))
args.Set("uid", fmt.Sprintf("%d", 1))
args.Set("phoneNumber", "13262609601")
args.Set("registerTime", fmt.Sprintf("%d", time.Now().Unix()))
args.Set("registerIp", ip)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
level, err := d.RegisterProtection(c, args, ip)
ctx.Convey("Then err should be nil.level should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(level, convey.ShouldNotBeNil)
})
})
})
}

View File

@ -0,0 +1,96 @@
package dao
import (
"context"
"fmt"
"go-common/library/cache/redis"
"go-common/library/log"
)
const (
_keyWaitBlock = "wb_" // b_batch_no wait block
_preLock = "lk_"
)
// keyWaitBlock return block cache key.
func keyWaitBlock(batchNo int64) string {
return _keyWaitBlock + fmt.Sprintf("%d", batchNo)
}
func lockKey(key int64) string {
return fmt.Sprintf("%s%d", _preLock, key)
}
// AddBlockCache add block cache.
func (d *Dao) AddBlockCache(c context.Context, mid int64, score int8, blockNo int64) (err error) {
var (
key = keyWaitBlock(blockNo)
)
conn := d.redis.Get(c)
defer conn.Close()
if err = conn.Send("ZADD", key, score, mid); err != nil {
log.Error("conn.Send(ZADD %s,%d,%d) error(%v)", key, score, mid, err)
return
}
if err = conn.Send("EXPIRE", key, d.expire); err != nil {
log.Error("conn.Send(EXPIRE) error(%v)", err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush() error(%v)", err)
return
}
for i := 0; i < 2; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive() error(%v)", err)
return
}
}
return
}
// BlockMidCache get wait block mids.
func (d *Dao) BlockMidCache(c context.Context, batchNo int64, num int64) (res []int64, err error) {
var (
conn = d.redis.Get(c)
key = keyWaitBlock(batchNo)
)
defer conn.Close()
if res, err = redis.Int64s(conn.Do("ZREVRANGEBYSCORE", key, "+inf", "-inf", "LIMIT", 0, num)); err != nil {
log.Error("redis(ZREVRANGEBYSCORE %s,%d) error(%v)", key, num, err)
return
}
return
}
//SetNXLockCache redis lock.
func (d *Dao) SetNXLockCache(c context.Context, k int64) (res bool, err error) {
var (
key = lockKey(k)
conn = d.redis.Get(c)
)
defer conn.Close()
if res, err = redis.Bool(conn.Do("SETNX", key, "1")); err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("conn.Do(SETNX(%d)) error(%v)", key, err)
return
}
}
if res {
if _, err = redis.Bool(conn.Do("EXPIRE", key, d.verifyExpire)); err != nil {
log.Error("conn.Do(EXPIRE, %s, %d) error(%v)", key, d.verifyExpire, err)
return
}
}
return
}
// PingRedis check redis connection
func (d *Dao) PingRedis(c context.Context) (err error) {
conn := d.redis.Get(c)
_, err = conn.Do("SET", "PING", "PONG")
conn.Close()
return
}

View File

@ -0,0 +1,99 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaokeyWaitBlock(t *testing.T) {
convey.Convey("keyWaitBlock", t, func(ctx convey.C) {
var (
batchNo = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := keyWaitBlock(batchNo)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaolockKey(t *testing.T) {
convey.Convey("lockKey", t, func(ctx convey.C) {
var (
key = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := lockKey(key)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddBlockCache(t *testing.T) {
convey.Convey("AddBlockCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
score = int8(0)
blockNo = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AddBlockCache(c, mid, score, blockNo)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoBlockMidCache(t *testing.T) {
convey.Convey("BlockMidCache", t, func(ctx convey.C) {
var (
c = context.Background()
batchNo = int64(0)
num = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.BlockMidCache(c, batchNo, num)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSetNXLockCache(t *testing.T) {
convey.Convey("SetNXLockCache", t, func(ctx convey.C) {
var (
c = context.Background()
k = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.SetNXLockCache(c, k)
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 TestDaoPingRedis(t *testing.T) {
convey.Convey("PingRedis", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.PingRedis(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@ -0,0 +1,50 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"config.go",
"databus.go",
"event.go",
"eventmsg.go",
"factor.go",
"factor_group.go",
"params.go",
"punishment.go",
"qcloud.go",
"risk.go",
"rpc.go",
"service.go",
"spy.go",
"stat.go",
"user_event_history.go",
"user_info.go",
],
importpath = "go-common/app/service/main/spy/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/account/model:go_default_library",
"//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,35 @@
package model
import accmdl "go-common/app/service/main/account/model"
// TelInfo def.
type TelInfo struct {
Mid int64 `json:"mid"`
Tel string `json:"tel"`
JoinIP string `json:"join_ip"`
JoinTime int64 `json:"join_time"`
}
// AuditInfo is.
type AuditInfo struct {
Mid int64 `json:"mid"`
BindTel bool `json:"bind_tel"`
BindMail bool `json:"bind_mail"`
Rank int64 `json:"rank"`
SpaceSta int64 `json:"spacesta"`
}
// ProfileInfo profile info.
type ProfileInfo = accmdl.Profile
// TelRiskInfo tel risk info.
type TelRiskInfo struct {
TelRiskLevel int8
RestoreHistory *UserEventHistory
UnicomGiftState int
}
// UnicomGiftState unicom gift state.
type UnicomGiftState struct {
State int `json:"state"`
}

View File

@ -0,0 +1,39 @@
package model
import "time"
// config properties.
const (
LimitBlockCount = "limitBlockCount"
LessBlockScore = "lessBlockScore"
AutoBlock = "autoBlock"
AutoBlockOpen = 1
)
const (
//BlockReasonSize block reason size
BlockReasonSize = 4
//BlockLockKey cycle block
BlockLockKey = "cycleblock"
//VipEnableStatus enable status
VipEnableStatus int32 = 1
//VipNonType non vip
VipNonType int32 = 0
// ReliveCheckTimes relive check times
ReliveCheckTimes = 1
// DoubleCheckRemake double check remake
DoubleCheckRemake = "导入二次验证,恢复行为得分"
// RetryTimes retry times
RetryTimes = 3
// SpyInitScore spy init score
SpyInitScore = 100
)
// Config def.
type Config struct {
ID int64
Property string
Name string
Val string
Ctime time.Time
}

View File

@ -0,0 +1,20 @@
package model
// ScoreChange DataBus spy score change.
type ScoreChange struct {
Mid int64 `json:"mid"`
Score int8 `json:"score"`
BaseScore int8 `json:"base_score"`
EventScore int8 `json:"event_score"`
TS int64 `json:"ts"`
Reason string `json:"reason"`
RiskLevel int8 `json:"risk_level"`
}
const (
//CoinReason coin reason ref update score
CoinReason = "coin-service"
//CoinHighRisk coin high risk
CoinHighRisk = 7
)

View File

@ -0,0 +1,16 @@
package model
import (
"go-common/library/time"
)
// Event def.
type Event struct {
ID int64
Name string // 事件标示
NickName string // 事件可读昵称
ServiceID int64
Status int8 // 0:删除 1:未删除
CTime time.Time
MTime time.Time
}

View File

@ -0,0 +1,20 @@
package model
import (
"go-common/library/time"
)
// EventMessage event from bigdata def.
type EventMessage struct {
Time time.Time `json:"time"`
IP string `json:"ip"`
Service string `json:"service"`
Event string `json:"event"`
ActiveMid int64 `json:"active_mid"`
TargetMid int64 `json:"target_mid"`
TargetID int64 `json:"target_id"`
Args interface{} `json:"args"`
Result string `json:"result"`
Effect string `json:"effect"`
RiskLevel int8 `json:"risk_level"`
}

View File

@ -0,0 +1,18 @@
package model
import (
"go-common/library/time"
)
// Factor def.
type Factor struct {
ID int64
NickName string //风险因子名字
ServiceID int64
EventID int64
GroupID int64
RiskLevel int8 //风险等级1-9
FactorVal float64 //风险得分
CTime time.Time
MTime time.Time
}

View File

@ -0,0 +1,12 @@
package model
import (
"go-common/library/time"
)
// FactorGroup is.
type FactorGroup struct {
ID int64
Name string //风险因子组名
CTime time.Time
}

View File

@ -0,0 +1,7 @@
package model
// NotifyInfo notify.
type NotifyInfo struct {
Mid int64 `json:"mid"`
Action string `json:"action"`
}

View File

@ -0,0 +1,20 @@
package model
import (
"go-common/library/time"
)
const (
//PunishmentTypeBlock 封禁
PunishmentTypeBlock = 1
)
// Punishment def.
type Punishment struct {
ID int64
Mid int64
Type int8 //封禁原因
Reason string //惩罚原因
CTime time.Time
MTime time.Time
}

View File

@ -0,0 +1,23 @@
package model
// Reg Pro args.
const (
AccountType = 4
)
// Tel level .
const (
Nomal int8 = iota
LevelOne
LevelTwo
LevelThree
LevelFour
)
// QcloudRegProResp def.
type QcloudRegProResp struct {
Code int `json:"code"`
CodeDesc string `json:"codeDesc"`
Message string `json:"message"`
Level int8 `json:"level"`
}

View File

@ -0,0 +1,19 @@
package model
import "time"
// Tel Expire
const (
TelExpireMonth = 3
QcloudType = 1
)
// TelRiskLevel def.
type TelRiskLevel struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Level int8 `json:"level"`
Origin int8 `json:"origin"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
}

View File

@ -0,0 +1,53 @@
package model
import (
"go-common/library/time"
)
// ArgReBuild rebuild args
type ArgReBuild struct {
Mid int64
Reason string
}
// ArgReset is.
type ArgReset struct {
Mid int64
ReLiveTime bool
EventScore bool
BaseScore bool
Operator string
}
// ArgUserScore rpc arg for getting user score.
type ArgUserScore struct {
Mid int64
IP string
}
// ArgHandleEvent rpc arg for handling spy event.
type ArgHandleEvent struct {
Time time.Time
IP string `json:"ip"`
Service string `json:"service"`
Event string `json:"event"`
ActiveMid int64 `json:"active_mid"`
TargetMid int64 `json:"target_mid"`
TargetID int64 `json:"target_id"`
Args interface{} `json:"args"`
Result string `json:"result"`
Effect string `json:"effect"`
RiskLevel int8 `json:"risk_level"`
}
// ArgUser rpc arg for getting user info.
type ArgUser struct {
Mid int64
IP string
}
// ArgStat rpc arg for getting user stat.
type ArgStat struct {
ID int64
Mid int64
}

View File

@ -0,0 +1,15 @@
package model
import (
"go-common/library/time"
)
// Service def.
type Service struct {
ID int64
Name string //服务标识
NickName string //服务可读昵称
Status int8
CTime time.Time
MTime time.Time
}

View File

@ -0,0 +1,7 @@
package model
// UserScore rpc return for getting user score.
type UserScore struct {
Mid int64 `json:"mid"`
Score int8 `json:"score"`
}

View File

@ -0,0 +1,8 @@
package model
// Statistics def.
type Statistics struct {
Quantity int64 `json:"quantity"`
EventID int64 `json:"event_id"`
EventName string `json:"event_name"`
}

View File

@ -0,0 +1,19 @@
package model
import (
"go-common/library/time"
)
// UserEventHistory history of user event def.
type UserEventHistory struct {
ID int64
Mid int64
EventID int64
Score int8
BaseScore int8
EventScore int8
Remark string
Reason string // 事件原因 == eventmsg.Effect
FactorVal float64
CTime time.Time
}

View File

@ -0,0 +1,25 @@
package model
import (
"go-common/library/time"
)
const (
// StateNormal UserInfo 正常状态
StateNormal = 0
// StateBlock UserInfo 封禁状态
StateBlock = 1
)
// UserInfo def.
type UserInfo struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Score int8 `json:"score"` //真实得分
BaseScore int8 `json:"base_score"` //基础信息得分
EventScore int8 `json:"event_score"` //事件得分
State int8 `json:"state"` //状态 : 正常/封禁
ReliveTimes int8 `json:"relive_times"` //画像得分恢复次数
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}

View File

@ -0,0 +1,42 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["spy_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = ["//app/service/main/spy/model:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["spy.go"],
importpath = "go-common/app/service/main/spy/rpc/client",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/spy/model:go_default_library",
"//library/net/rpc: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,96 @@
package spy
import (
"context"
"go-common/app/service/main/spy/model"
"go-common/library/net/rpc"
)
const (
_addEvent = "RPC.HandleEvent"
_userScore = "RPC.UserScore"
_reBuildPortrait = "RPC.ReBuildPortrait"
//_resetManually = "RPC.ResetManually"
_updateBaseScore = "RPC.UpdateBaseScore"
_refreshBaseScore = "RPC.RefreshBaseScore"
_updateEventScore = "RPC.UpdateEventScore"
_userInfo = "RPC.UserInfo"
_clearReliveTimes = "RPC.ClearReliveTimes"
_statByID = "RPC.StatByID"
)
const (
_appid = "account.service.spy"
)
var (
_noRes = &struct{}{}
)
// Service struct info.
type Service struct {
client *rpc.Client2
}
// New create instance of service and return.
func New(c *rpc.ClientConfig) (s *Service) {
s = &Service{}
s.client = rpc.NewDiscoveryCli(_appid, c)
return
}
// HandleEvent add spy event to user.
func (s *Service) HandleEvent(c context.Context, arg *model.ArgHandleEvent) (err error) {
err = s.client.Call(c, _addEvent, arg, _noRes)
return
}
// UserScore archive get user spy score.
func (s *Service) UserScore(c context.Context, arg *model.ArgUserScore) (res *model.UserScore, err error) {
res = &model.UserScore{}
err = s.client.Call(c, _userScore, arg, res)
return
}
// ReBuildPortrait rebuild user risk portrait by task.
func (s *Service) ReBuildPortrait(c context.Context, arg *model.ArgReBuild) (err error) {
err = s.client.Call(c, _reBuildPortrait, arg, _noRes)
return
}
// UpdateBaseScore cli.
func (s *Service) UpdateBaseScore(c context.Context, arg *model.ArgReset) (err error) {
err = s.client.Call(c, _updateBaseScore, arg, _noRes)
return
}
// RefreshBaseScore cli.
func (s *Service) RefreshBaseScore(c context.Context, arg *model.ArgReset) (err error) {
err = s.client.Call(c, _refreshBaseScore, arg, _noRes)
return
}
// UpdateEventScore cli.
func (s *Service) UpdateEventScore(c context.Context, arg *model.ArgReset) (err error) {
err = s.client.Call(c, _updateEventScore, arg, _noRes)
return
}
// UserInfo cli.
func (s *Service) UserInfo(c context.Context, arg *model.ArgUser) (res *model.UserInfo, err error) {
err = s.client.Call(c, _userInfo, arg, res)
return
}
// ClearReliveTimes cli.
func (s *Service) ClearReliveTimes(c context.Context, arg *model.ArgReset) (err error) {
err = s.client.Call(c, _clearReliveTimes, arg, _noRes)
return
}
// StatByID cli.
func (s *Service) StatByID(c context.Context, arg *model.ArgStat) (stat []*model.Statistics, err error) {
err = s.client.Call(c, _statByID, arg, &stat)
return
}

View File

@ -0,0 +1,47 @@
package spy
import (
"context"
"testing"
"time"
model "go-common/app/service/main/spy/model"
)
func TestSpy(t *testing.T) {
s := New(nil)
time.Sleep(2 * time.Second)
testUpdateEventScore(t, s)
testUpdateBaseScore(t, s)
testUserScore(t, s)
testHandleEvent(t, s)
testReBuildPortrait(t, s)
}
func testUpdateEventScore(t *testing.T, s *Service) {
t.Log(s.UpdateEventScore(context.TODO(), &model.ArgReset{Mid: 23333, Operator: "admin test"}))
}
func testUpdateBaseScore(t *testing.T, s *Service) {
t.Log(s.UpdateBaseScore(context.TODO(), &model.ArgReset{Mid: 23333, Operator: "admin test"}))
}
func testUserScore(t *testing.T, s *Service) {
t.Log(s.UserScore(context.TODO(), &model.ArgUserScore{Mid: 23333, IP: "127.0.0.1"}))
}
func testHandleEvent(t *testing.T, s *Service) {
t.Log(s.HandleEvent(context.TODO(), &model.ArgHandleEvent{
IP: "127.0.0.1",
Service: "spy_service",
Event: "bind_mail_only",
ActiveMid: 23333,
TargetMid: 23333,
Effect: "",
RiskLevel: 1,
}))
}
func testReBuildPortrait(t *testing.T, s *Service) {
t.Log(s.ReBuildPortrait(context.TODO(), &model.ArgReBuild{Mid: 23333}))
}

View File

@ -0,0 +1,35 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["rpc.go"],
importpath = "go-common/app/service/main/spy/rpc/server",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/spy/conf:go_default_library",
"//app/service/main/spy/model:go_default_library",
"//app/service/main/spy/service:go_default_library",
"//library/net/rpc:go_default_library",
"//library/net/rpc/context: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,107 @@
package rpc
import (
cmmdl "go-common/app/service/main/spy/model"
"go-common/library/net/rpc"
"go-common/library/net/rpc/context"
"go-common/app/service/main/spy/conf"
"go-common/app/service/main/spy/model"
"go-common/app/service/main/spy/service"
)
// RPC server def.
type RPC struct {
s *service.Service
}
// New create instance of rpc server2 and return.
func New(c *conf.Config, s *service.Service) (svr *rpc.Server) {
r := &RPC{s: s}
svr = rpc.NewServer(c.RPCServer)
if err := svr.Register(r); err != nil {
panic(err)
}
return
}
// Ping check rpc server health.
func (r *RPC) Ping(c context.Context, arg *struct{}, res *struct{}) (err error) {
return
}
// UserScore rpc req for getting user spy score.
func (r *RPC) UserScore(c context.Context, arg *cmmdl.ArgUserScore, res *cmmdl.UserScore) (err error) {
var (
ui *model.UserInfo
)
if ui, err = r.s.UserInfo(c, arg.Mid, arg.IP); ui != nil && err == nil {
*res = cmmdl.UserScore{Mid: ui.Mid, Score: ui.Score}
}
return
}
// HandleEvent rpc req for handling spy event , maybe from spy-job.
func (r *RPC) HandleEvent(c context.Context, arg *cmmdl.ArgHandleEvent, res *struct{}) (err error) {
var event = &model.EventMessage{
Time: arg.Time,
IP: arg.IP,
Service: arg.Service,
Event: arg.Event,
ActiveMid: arg.ActiveMid,
TargetMid: arg.TargetMid,
TargetID: arg.TargetID,
Args: arg.Args,
Result: arg.Result,
Effect: arg.Effect,
RiskLevel: arg.RiskLevel,
}
return r.s.HandleEvent(c, event)
}
// ReBuildPortrait rpc.
func (r *RPC) ReBuildPortrait(c context.Context, arg *cmmdl.ArgReBuild, res *struct{}) (err error) {
return r.s.ReBuildPortrait(c, arg.Mid, arg.Reason)
}
// UpdateBaseScore rpc.
func (r *RPC) UpdateBaseScore(c context.Context, arg *cmmdl.ArgReset, res *struct{}) (err error) {
return r.s.UpdateBaseScore(c, arg)
}
// UpdateEventScore rpc.
func (r *RPC) UpdateEventScore(c context.Context, arg *cmmdl.ArgReset, res *struct{}) (err error) {
return r.s.UpdateEventScore(c, arg)
}
// UserInfo rpc.
func (r *RPC) UserInfo(c context.Context, arg *cmmdl.ArgUser, res *cmmdl.UserInfo) (err error) {
var (
ui *model.UserInfo
)
if ui, err = r.s.UserInfo(c, arg.Mid, arg.IP); ui != nil && err == nil {
*res = *ui
}
return
}
// ClearReliveTimes rpc.
func (r *RPC) ClearReliveTimes(c context.Context, arg *cmmdl.ArgReset, res *struct{}) (err error) {
return r.s.ClearReliveTimes(c, arg)
}
// StatByID rpc.
func (r *RPC) StatByID(c context.Context, arg *cmmdl.ArgStat, res *[]*cmmdl.Statistics) (err error) {
var (
stat []*model.Statistics
)
if stat, err = r.s.StatByIDGroupEvent(c, arg.Mid, arg.ID); stat != nil && err == nil {
*res = stat
}
return
}
// RefreshBaseScore rpc.
func (r *RPC) RefreshBaseScore(c context.Context, arg *cmmdl.ArgReset, res *struct{}) (err error) {
return r.s.RefreshBaseScore(c, arg)
}

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 = ["server.go"],
importpath = "go-common/app/service/main/spy/server/grpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/spy/api:go_default_library",
"//app/service/main/spy/model:go_default_library",
"//app/service/main/spy/service:go_default_library",
"//library/net/rpc/warden: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,138 @@
// Package server generate by warden_gen
package server
import (
"context"
pb "go-common/app/service/main/spy/api"
"go-common/app/service/main/spy/model"
service "go-common/app/service/main/spy/service"
"go-common/library/net/rpc/warden"
)
// New Spy warden rpc server
func New(c *warden.ServerConfig, svr *service.Service) *warden.Server {
ws := warden.NewServer(c)
pb.RegisterSpyServer(ws.Server(), &server{svr})
_, err := ws.Start()
if err != nil {
panic(err)
}
return ws
}
type server struct {
svr *service.Service
}
var _ pb.SpyServer = &server{}
// Ping check dao health.
func (s *server) Ping(ctx context.Context, req *pb.PingReq) (*pb.PingReply, error) {
return &pb.PingReply{}, nil
}
// StatByID spy stat by id or mid.
func (s *server) StatByID(ctx context.Context, req *pb.StatByIDReq) (*pb.StatByIDReply, error) {
statistics, err := s.svr.StatByID(ctx, req.Mid, req.Id)
if err != nil {
return nil, err
}
reply := new(pb.StatByIDReply)
reply.DeepCopyFromStatistics(statistics)
return reply, nil
}
// StatByIDGroupEvent spy stat by id or mid.
func (s *server) StatByIDGroupEvent(ctx context.Context, req *pb.StatByIDGroupEventReq) (*pb.StatByIDGroupEventReply, error) {
statistics, err := s.svr.StatByIDGroupEvent(ctx, req.Mid, req.Id)
if err != nil {
return nil, err
}
reply := new(pb.StatByIDGroupEventReply)
reply.DeepCopyFromStatistics(statistics)
return reply, nil
}
// PurgeUser purge user info
func (s *server) PurgeUser(ctx context.Context, req *pb.PurgeUserReq) (*pb.PurgeUserReply, error) {
return &pb.PurgeUserReply{}, s.svr.PurgeUser(ctx, req.Mid, req.Action)
}
// HandleEvent handle spy-event.
func (s *server) HandleEvent(ctx context.Context, req *pb.HandleEventReq) (*pb.HandleEventReply, error) {
eventMsg := new(model.EventMessage)
req.DeepCopyAsIntoEventMessage(eventMsg)
return &pb.HandleEventReply{}, s.svr.HandleEvent(ctx, eventMsg)
}
// UserInfo get UserInfo by mid , from cache or db or generate.
func (s *server) UserInfo(ctx context.Context, req *pb.UserInfoReq) (*pb.UserInfoReply, error) {
ui, err := s.svr.UserInfo(ctx, req.Mid, req.Ip)
if err != nil {
return nil, err
}
reply := new(pb.UserInfoReply)
reply.DeepCopyFromUserInfo(ui)
return reply, nil
}
// UserInfoAsyn get UserInfo by mid , from cache or db or asyn generate.
func (s *server) UserInfoAsyn(ctx context.Context, req *pb.UserInfoAsynReq) (*pb.UserInfoAsynReply, error) {
ui, err := s.svr.UserInfoAsyn(ctx, req.Mid)
if err != nil {
return nil, err
}
reply := new(pb.UserInfoAsynReply)
reply.DeepCopyFromUserInfo(ui)
return reply, nil
}
// ReBuildPortrait reBuild user info.
func (s *server) ReBuildPortrait(ctx context.Context, req *pb.ReBuildPortraitReq) (*pb.ReBuildPortraitReply, error) {
return &pb.ReBuildPortraitReply{}, s.svr.ReBuildPortrait(ctx, req.Mid, req.Reason)
}
// UpdateUserScore update user score
func (s *server) UpdateUserScore(ctx context.Context, req *pb.UpdateUserScoreReq) (*pb.UpdateUserScoreReply, error) {
return &pb.UpdateUserScoreReply{}, s.svr.UpdateUserScore(ctx, req.Mid, req.Ip, req.Effect)
}
// RefreshBaseScore refresh base score.
func (s *server) RefreshBaseScore(ctx context.Context, req *pb.RefreshBaseScoreReq) (*pb.RefreshBaseScoreReply, error) {
argReset := new(model.ArgReset)
req.DeepCopyAsIntoArgReset(argReset)
return &pb.RefreshBaseScoreReply{}, s.svr.RefreshBaseScore(ctx, argReset)
}
// UpdateBaseScore update base score.
func (s *server) UpdateBaseScore(ctx context.Context, req *pb.UpdateBaseScoreReq) (*pb.UpdateBaseScoreReply, error) {
argReset := new(model.ArgReset)
req.DeepCopyAsIntoArgReset(argReset)
return &pb.UpdateBaseScoreReply{}, s.svr.UpdateBaseScore(ctx, argReset)
}
// UpdateEventScore update event score.
func (s *server) UpdateEventScore(ctx context.Context, req *pb.UpdateEventScoreReq) (*pb.UpdateEventScoreReply, error) {
argReset := new(model.ArgReset)
req.DeepCopyAsIntoArgReset(argReset)
return &pb.UpdateEventScoreReply{}, s.svr.UpdateEventScore(ctx, argReset)
}
// ClearReliveTimes clear times.
func (s *server) ClearReliveTimes(ctx context.Context, req *pb.ClearReliveTimesReq) (*pb.ClearReliveTimesReply, error) {
argReset := new(model.ArgReset)
req.DeepCopyAsIntoArgReset(argReset)
return &pb.ClearReliveTimesReply{}, s.svr.ClearReliveTimes(ctx, argReset)
}
// Info get user info by mid.
func (s *server) Info(ctx context.Context, req *pb.InfoReq) (*pb.InfoReply, error) {
ui, err := s.svr.Info(ctx, req.Mid)
if err != nil {
return nil, err
}
reply := new(pb.InfoReply)
reply.DeepCopyFromUserInfo(ui)
return reply, nil
}

View File

@ -0,0 +1,40 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"http.go",
"spy.go",
],
importpath = "go-common/app/service/main/spy/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/spy/conf:go_default_library",
"//app/service/main/spy/model:go_default_library",
"//app/service/main/spy/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify: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,58 @@
package http
import (
"net/http"
"go-common/app/service/main/spy/conf"
"go-common/app/service/main/spy/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
spySvc *service.Service
verifyN *verify.Verify
)
// Init init http server.
func Init(c *conf.Config, s *service.Service) {
spySvc = s
verifyN = verify.New(nil)
// init inner router
engineInner := bm.DefaultServer(c.BM)
innerRouter(engineInner)
// init local server
if err := engineInner.Start(); err != nil {
log.Error("xhttp.Serve error(%v)", err)
panic(err)
}
}
// innerRouter init inner router.
func innerRouter(e *bm.Engine) {
// health check
e.Ping(ping)
e.Register(register)
//new defined api lists
group := e.Group("/x/internal/v1/spy", verifyN.Verify)
{
group.GET("/info", info)
group.GET("/purge", purgeUser)
group.POST("/purge2", purgeUser2)
group.GET("/stat", stat)
}
}
// ping check server ok.
func ping(c *bm.Context) {
if spySvc.Ping(c) != nil {
log.Error("spy-service service ping error")
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}
// register check server ok.
func register(c *bm.Context) {
c.JSON(map[string]interface{}{}, nil)
}

View File

@ -0,0 +1,105 @@
package http
import (
"encoding/json"
"strconv"
"go-common/app/service/main/spy/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
func info(c *bm.Context) {
var (
err error
mid int64
midStr = c.Request.Form.Get("mid")
)
if mid, err = strconv.ParseInt(midStr, 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
ui, err := spySvc.Info(c, mid)
if err != nil {
log.Error("spySvc.UserInfo(%d), ui(%v), err(%v)", mid, ui, err)
c.JSON(nil, ecode.ServerErr)
return
}
c.JSON(&model.UserScore{Mid: ui.Mid, Score: ui.Score}, nil)
}
func purgeUser(c *bm.Context) {
var (
err error
mid int64
params = c.Request.Form
midStr = params.Get("mid")
action = params.Get("modifiedAttr")
)
if mid, err = strconv.ParseInt(midStr, 10, 64); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if action == "" {
c.JSON(nil, ecode.RequestErr)
return
}
err = spySvc.PurgeUser(c, mid, action)
c.JSON(nil, err)
}
func purgeUser2(c *bm.Context) {
var (
err error
params = c.Request.Form
msg = params.Get("msg")
info = new(model.NotifyInfo)
)
if err = json.Unmarshal([]byte(msg), &info); err != nil {
log.Error("purgeUser2 (%s) json.Unmarshal error(%v)", msg, err)
c.JSON(nil, ecode.RequestErr)
return
}
if info == nil {
c.JSON(nil, ecode.RequestErr)
return
}
if info.Action == "" || info.Mid == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = spySvc.PurgeUser(c, info.Mid, info.Action); err != nil {
log.Error("purgeUser2 (%+v) error(%v)", info, err)
}
c.JSON(nil, err)
}
func stat(c *bm.Context) {
var (
err error
mid, id int64
params = c.Request.Form
midStr = params.Get("mid")
idStr = params.Get("id")
)
if mid, err = strconv.ParseInt(midStr, 10, 64); midStr != "" && err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if id, err = strconv.ParseInt(idStr, 10, 64); idStr != "" && err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
if id == 0 && mid == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
stat, err := spySvc.StatByID(c, mid, id)
if err != nil {
log.Error("spySvc.StatByID err(%v)", err)
c.JSON(nil, ecode.ServerErr)
return
}
c.JSON(stat, nil)
}

View File

@ -0,0 +1,73 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"block_test.go",
"rule_test.go",
"service_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/spy/conf:go_default_library",
"//app/service/main/spy/dao:go_default_library",
"//app/service/main/spy/model:go_default_library",
"//library/cache/redis:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/ip:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"block.go",
"rule.go",
"service.go",
"spy.go",
"stat.go",
],
importpath = "go-common/app/service/main/spy/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/account/model:go_default_library",
"//app/service/main/account/rpc/client:go_default_library",
"//app/service/main/spy/conf:go_default_library",
"//app/service/main/spy/dao:go_default_library",
"//app/service/main/spy/model:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/ip:go_default_library",
"//library/net/metadata:go_default_library",
"//library/stat/prom:go_default_library",
"//vendor/github.com/pkg/errors: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,51 @@
package service
import (
"context"
"go-common/library/log"
"go-common/library/net/metadata"
)
const (
_banned = 1
_unBindTel = "unBindTel"
_updateTel = "updateTel"
_updateEmail = "updateEmail"
_updateUname = "updateUname"
_updateFace = "updateFace"
_updateIDEN = "updateIDEN"
)
// PurgeUser purge user info
func (s *Service) PurgeUser(c context.Context, mid int64, action string) (err error) {
ui, err := s.UserInfoAsyn(c, mid)
if err != nil {
log.Error("purge user(%d) failed", mid)
return
}
if ui == nil || ui.State == _banned {
log.Error("ui not fund or banned:%v", ui)
return
}
var effect string
switch action {
case _unBindTel:
effect = "解除绑定手机"
case _updateTel:
effect = "更新绑定手机"
case _updateEmail:
effect = "更新绑定邮箱"
case _updateUname, _updateFace:
effect = "修改账号资料"
case _updateIDEN:
effect = "完成实名认证"
default:
log.Error("unhandle action(%s) for mid(%d)", action, mid)
}
ip := metadata.String(c, metadata.RemoteIP)
s.updatescore(func() {
s.UpdateUserScore(context.TODO(), mid, ip, effect)
})
return
}

View File

@ -0,0 +1,164 @@
package service
import (
"bytes"
"context"
"fmt"
"time"
accmdl "go-common/app/service/main/account/model"
"go-common/app/service/main/spy/model"
"go-common/library/log"
)
// HandlerFunc block filter handler function.
type HandlerFunc func(af *Args)
// Args filter args.
type Args struct {
block bool
ui *model.UserInfo
}
//BlockNo block no.
func (s *Service) BlockNo(seconds int64) int64 {
return time.Now().Unix() / seconds
}
func (s *Service) scoreLessHandler(af *Args) {
v, ok := s.Config(model.LessBlockScore)
if !ok {
log.Error("scoreLessHandler get config error(%s,%v)", model.LessBlockScore, s.spyConfig)
return
}
if af.ui.Score <= v.(int8) {
af.block = true
return
}
}
//reVerifyHandler double check user lv and vip info
func (s *Service) reVerifyHandler(c context.Context, ui *model.UserInfo) (b bool, err error) {
b = true
account, err := s.accInfoRetry(c, ui.Mid)
if err != nil || account == nil {
return
}
// vip or lv4
if (account.Level < s.c.Property.DoubleCheckLevel) &&
(account.Vip.Status != model.VipEnableStatus || account.Vip.Type == model.VipNonType) {
return
}
udb, err := s.dao.UserInfo(c, ui.Mid)
if err != nil {
log.Error(" s.dao.UserInfo(%d) err(%v)", ui.Mid, err)
return
}
if udb.ReliveTimes > model.ReliveCheckTimes {
s.promBlockInfo.Incr("security_login_times_out_count")
return
}
b = false
l, err := s.dao.SetNXLockCache(c, ui.Mid)
if !l || err != nil {
log.Error("cycleblock had run (%v,%v)", l, err)
return
}
if err = s.ReBuildPortrait(c, ui.Mid, model.DoubleCheckRemake); err != nil {
log.Error(" s.ReBuildPortrait(%d) err(%v)", ui.Mid, err)
return
}
reason, _ := s.blockReason(c, ui.Mid)
if err = s.dao.SecurityLogin(c, ui.Mid, reason); err != nil {
log.Error(" s.dao.SecurityLogin(%d) err(%v)", ui.Mid, err)
return
}
s.promBlockInfo.Incr("security_login_count")
return
}
// Verify block filter.
func (s *Service) Verify(c context.Context, af *Args, handlers ...HandlerFunc) (b bool) {
v, ok := s.Config(model.AutoBlock)
if !ok {
log.Error("Verfiy get config error(%s,%v)", model.AutoBlock, s.spyConfig)
return
}
if v.(int8) != model.AutoBlockOpen {
log.Info("autoBlock Close(%v)", af)
return
}
for _, h := range handlers {
h(af)
if b = af.block; b {
break
}
}
// double check
if b {
s.promBlockInfo.Incr("expect_block_count")
b, _ = s.reVerifyHandler(c, af.ui)
}
return
}
// BlockFilter do user block.
func (s *Service) BlockFilter(c context.Context, ui *model.UserInfo) (state int8, err error) {
var (
args = &Args{ui: ui}
hs = []HandlerFunc{s.scoreLessHandler}
blockNo = s.BlockNo(s.c.Property.Block.CycleTimes)
)
state = ui.State
if b := s.Verify(c, args, hs...); !b {
return
}
state = model.StateBlock
s.dao.AddBlockCache(c, ui.Mid, ui.Score, blockNo)
if err = s.dao.AddPunishmentQueue(c, ui.Mid, blockNo); err != nil {
log.Error("s.dao.AddPunishmentQueue(%d) error(%v)", ui.Mid, err)
return
}
return
}
func (s *Service) blockReason(c context.Context, mid int64) (reason string, remake string) {
var (
err error
hs []*model.UserEventHistory
buf bytes.Buffer
)
if hs, err = s.dao.HistoryList(c, mid, model.BlockReasonSize); err != nil || len(hs) == 0 {
log.Error("s.dao.HistoryList(%d) err(%v)", mid, err)
return
}
m := make(map[string]int)
for _, v := range hs {
if v.Reason == model.DoubleCheckRemake {
continue
}
if m[v.Reason] == 0 {
m[v.Reason] = 1
} else {
m[v.Reason] = m[v.Reason] + 1
}
}
for k, v := range m {
buf.WriteString(k)
buf.WriteString("x")
buf.WriteString(fmt.Sprintf("%d ", v))
}
reason = buf.String()
return
}
func (s *Service) accInfoRetry(c context.Context, mid int64) (account *accmdl.Card, err error) {
for i := 1; i <= model.RetryTimes; i++ {
account, err = s.accRPC.Card3(c, &accmdl.ArgMid{Mid: mid})
if account == nil || err != nil {
log.Error(" s.accRPC.Infos2(%d) err(%v)", mid, err)
continue
}
}
return
}

View File

@ -0,0 +1,129 @@
package service
import (
"context"
"fmt"
"testing"
"go-common/app/service/main/spy/model"
spy "go-common/app/service/main/spy/model"
"go-common/library/net/ip"
. "github.com/smartystreets/goconvey/convey"
)
var (
testLowMid int64 = 59999
testLowScore int8 = 5
testHighScore int8 = 90
testLv5Mid int64 = 15555180
testNoLv5Mid int64 = 200
)
func Test_Verfiy(t *testing.T) {
Convey("Test_Verfiy block ", t, WithService(func(s *Service) {
ui, err := s.UserInfo(c, testLowMid, "")
fmt.Println(ui)
So(ui, ShouldNotBeEmpty)
So(err, ShouldBeNil)
hs := []HandlerFunc{s.scoreLessHandler}
Convey("Test_Verfiy scoreLessHandler low score ", WithService(func(s *Service) {
ui.Score = testLowScore
args := &Args{ui: ui}
b := s.Verify(c, args, hs...)
fmt.Println("b", b, ui.Score)
So(b, ShouldBeTrue)
}))
Convey("Test_Verfiy scoreLessHandler high score ", WithService(func(s *Service) {
ui.Score = testHighScore
args := &Args{ui: ui}
b := s.Verify(c, args, hs...)
fmt.Println("b", b, ui.Score)
So(b, ShouldBeFalse)
}))
}))
}
func Test_BlockFilter(t *testing.T) {
Convey("Test_BlockFilter filter ", t, WithService(func(s *Service) {
var (
c = context.TODO()
)
ui, err := s.UserInfo(c, testLowMid, "")
fmt.Println(ui)
So(ui, ShouldNotBeEmpty)
So(err, ShouldBeNil)
tx, err := s.dao.BeginTran(c)
So(err, ShouldBeNil)
Convey("Test_BlockFilter block ", WithService(func(s *Service) {
ret, err := s.dao.BlockMidCache(c, s.BlockNo(s.c.Property.Block.CycleTimes), 10)
So(err, ShouldBeNil)
So(ret, ShouldBeNil)
ui.Score = testLowScore
state, err := s.BlockFilter(context.TODO(), ui)
So(err, ShouldBeNil)
So(state == model.StateBlock, ShouldBeTrue)
err = tx.Commit()
So(err, ShouldBeNil)
Convey("Test_BlockFilter cache had mid ", WithService(func(s *Service) {
ret, err := s.dao.BlockMidCache(c, s.BlockNo(s.c.Property.Block.CycleTimes), 10)
fmt.Println("ret", ret)
So(err, ShouldBeNil)
So(ret, ShouldContain, ui.Mid)
}))
}))
Convey("Test_BlockFilter bo block ", WithService(func(s *Service) {
ui.Score = testHighScore
state, err := s.BlockFilter(context.TODO(), ui)
So(err, ShouldBeNil)
So(state == model.StateBlock, ShouldBeFalse)
err = tx.Commit()
So(err, ShouldBeNil)
}))
}))
}
func Test_ReVerify(t *testing.T) {
Convey("Test_ReVerify user lv check ", t, WithService(func(s *Service) {
var (
c = context.TODO()
)
Convey("test vip user ", WithService(func(s *Service) {
err := s.ClearReliveTimes(c, &spy.ArgReset{Mid: testLv5Mid, Operator: "yubaihai"})
So(err, ShouldBeNil)
ui, err := s.UserInfo(c, testLv5Mid, ip.InternalIP())
So(err, ShouldBeNil)
So(ui, ShouldNotBeEmpty)
fmt.Println("ui", ui)
b, err := s.reVerifyHandler(c, ui)
So(err, ShouldBeNil)
So(b, ShouldBeFalse)
// two
b, err = s.reVerifyHandler(c, ui)
So(err, ShouldBeNil)
So(b, ShouldBeFalse)
// three
b, err = s.reVerifyHandler(c, ui)
So(err, ShouldBeNil)
So(b, ShouldBeTrue)
}))
Convey("test no lv vip user ", WithService(func(s *Service) {
ui, err := s.UserInfo(c, testNoLv5Mid, ip.InternalIP())
So(err, ShouldBeNil)
So(ui, ShouldNotBeEmpty)
fmt.Println("ui", ui)
b, err := s.reVerifyHandler(c, ui)
So(err, ShouldBeNil)
So(b, ShouldBeTrue)
}))
}))
}

View File

@ -0,0 +1,439 @@
package service
import (
"context"
"go-common/app/service/main/spy/conf"
"go-common/app/service/main/spy/dao"
"go-common/app/service/main/spy/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
// RestoreBaseScoreEvent represents a event triggered when user resets base score.
RestoreBaseScoreEvent = "restore_base_score"
)
const (
_defaultService = ""
_defaultRiskLevel = 1
_telIsBound = "_telIsBound"
_telIsNotBound = "_telIsNotBound"
_telIsLowRisk = "_telIsLowRisk"
_telIsMediumRisk = "_telIsMediumRisk"
_telIsHighRisk = "_telIsHighRisk"
_telIsUnknownRisk = "_telIsUnknownRisk"
_mailIsBound = "_mailIsBound"
_mailIsNotBound = "_mailIsNotBound"
_idenIsAuthed = "_idenIsAuthed"
_idenIsNotAuthed = "_idenIsNotAuthed"
)
const (
// IterFail represents iteration failure.
IterFail IterState = iota
// IterSuccess represents iteration success.
IterSuccess
)
// Rule represents a rule.
type Rule = string
// Rules represents an array of rules.
type Rules = []Rule
// IterState represents the state of iteration.
type IterState = int
// RuleFunc represents a judgement function.
type RuleFunc func(info *JudgementInfo) (result bool, err error)
var ruleToFuncMaps = map[string]RuleFunc{
_telIsBound: telIsBound,
_telIsNotBound: telIsNotBound,
_telIsLowRisk: telIsLowRisk,
_telIsMediumRisk: telIsMediumRisk,
_telIsHighRisk: telIsHighRisk,
_telIsUnknownRisk: telIsUnknownRisk,
_mailIsBound: mailIsBound,
_mailIsNotBound: mailIsNotBound,
_idenIsAuthed: idenIsAuthed,
_idenIsNotAuthed: idenIsNotAuthed,
}
// FactoryMeta includes details to find a factor.
type FactoryMeta struct {
serviceName string
eventName string
riskLevel int8
}
// JudgementInfo includes all needed information to judge factor.
type JudgementInfo struct {
mid int64
ip string
ctx context.Context
s *Service
auditInfo *model.AuditInfo
profileInfo *model.ProfileInfo
telRiskInfo *model.TelRiskInfo
}
// RuleMap represents a map-like struct which contains rules and factoryMeta.
type RuleMap struct {
rules Rules
factoryMeta FactoryMeta
}
// NewJudgementInfo returns a new judgement info.
func NewJudgementInfo(c context.Context, s *Service, mid int64, ip string) *JudgementInfo {
return &JudgementInfo{
s: s,
mid: mid,
ctx: c,
ip: ip,
}
}
func (ji *JudgementInfo) getAuditInfo() (auditInfo *model.AuditInfo, err error) {
if ji.auditInfo != nil {
return ji.auditInfo, nil
}
auditInfo, err = ji.s.dao.AuditInfo(ji.ctx, ji.mid, ji.ip)
if err != nil {
log.Error("s.dao.AuditInfo(%d, %s) error(%v)", ji.mid, ji.ip, err)
return
}
ji.auditInfo = auditInfo
return
}
func (ji *JudgementInfo) getProfileInfo() (profileInfo *model.ProfileInfo, err error) {
if ji.profileInfo != nil {
return ji.profileInfo, nil
}
profileInfo, err = ji.s.dao.ProfileInfo(ji.ctx, ji.mid, ji.ip)
if err != nil {
log.Error("s.dao.ProfileInfo(%d, %s) error(%v)", ji.mid, ji.ip, err)
return
}
ji.profileInfo = profileInfo
return ji.profileInfo, nil
}
func (ji *JudgementInfo) getTelRiskInfo() (telRiskInfo *model.TelRiskInfo, err error) {
var (
telRiskLevel int8
event *model.Event
eventHistory *model.UserEventHistory
unicomGiftState int
)
if ji.telRiskInfo != nil {
return ji.telRiskInfo, nil
}
telRiskLevel, err = ji.s.TelRiskLevel(ji.ctx, ji.mid, "")
if err != nil {
log.Error("s.dao.TelRiskLevel(%d) error:(%v)", ji.mid, err)
return
}
if event, err = ji.s.dao.Event(ji.ctx, RestoreBaseScoreEvent); err != nil {
return
}
if eventHistory, err = ji.s.dao.EventHistoryByMidAndEvent(ji.ctx, ji.mid, event.ID); err != nil {
return
}
if unicomGiftState, err = ji.s.dao.UnicomGiftState(ji.ctx, ji.mid); err != nil {
return
}
ji.telRiskInfo = &model.TelRiskInfo{
TelRiskLevel: telRiskLevel,
RestoreHistory: eventHistory,
UnicomGiftState: unicomGiftState,
}
return ji.telRiskInfo, nil
}
func (s *Service) getRulesMap() []RuleMap {
return []RuleMap{
// 绑定手机状态:绑定手机,且天御认定为低风险 邮箱绑定状态any 实名认证状态:通过认证无论人工还是芝麻
{
factoryMeta: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindTelLowRiskAndIdenAuth,
riskLevel: _defaultRiskLevel,
},
rules: Rules{
_telIsBound, _telIsLowRisk, _idenIsAuthed,
}},
// 绑定手机状态:绑定手机,且天域认定为低风险 邮箱绑定状态any 实名认证状态:无
{
factoryMeta: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindTelLowRiskAndIdenUnauth,
riskLevel: _defaultRiskLevel,
},
rules: Rules{
_telIsBound, _telIsLowRisk, _idenIsNotAuthed,
}},
// 绑定手机状态:绑定手机,且天域认定为未知风险 邮箱绑定状态any 实名认证状态:通过认证无论人工还是芝麻
{
factoryMeta: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindTelUnknownRiskAndIdenAuth,
riskLevel: _defaultRiskLevel,
},
rules: Rules{
_telIsBound, _telIsUnknownRisk, _idenIsAuthed,
}},
// 绑定手机状态:绑定手机,且天域认定为中风险 邮箱绑定状态any 实名认证状态:通过认证无论人工还是芝麻
{
factoryMeta: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindTelMediumRiskAndIdenAuth,
riskLevel: _defaultRiskLevel,
},
rules: Rules{
_telIsBound, _telIsMediumRisk, _idenIsAuthed,
}},
// 绑定手机状态:绑定手机,且天域认定为未知风险 邮箱绑定状态any 实名认证状态:无
{
factoryMeta: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindTelUnknownRiskAndIdenUnauth,
riskLevel: _defaultRiskLevel,
},
rules: Rules{
_telIsBound, _telIsUnknownRisk, _idenIsNotAuthed,
}},
// 绑定手机状态:绑定手机,且天域认定为中风险 邮箱绑定状态any 实名认证状态:无
{
factoryMeta: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindTelMediumRiskAndIdenUnauth,
riskLevel: _defaultRiskLevel,
},
rules: Rules{
_telIsBound, _telIsMediumRisk, _idenIsNotAuthed,
}},
// 绑定手机状态:无 绑定邮箱状态:有 实名认证状态any
{
factoryMeta: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindMailAndIdenUnknown,
riskLevel: _defaultRiskLevel,
},
rules: Rules{
_telIsNotBound, _mailIsBound,
}},
// 绑定手机状态:绑定手机,且天域认定为高风险 邮箱绑定状态any 实名认证状态:实名认证,无论人工还是芝麻
{
factoryMeta: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindTelHighRiskAndIdenAuth,
riskLevel: _defaultRiskLevel,
},
rules: Rules{
_telIsBound, _telIsHighRisk, _idenIsAuthed,
}},
// 无绑定手机状态:绑定手机 绑定邮箱状态:无 实名认证状态:无
{
factoryMeta: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindNothingV2,
riskLevel: _defaultRiskLevel,
},
rules: Rules{
_telIsNotBound, _mailIsNotBound, _idenIsNotAuthed,
}},
// 无绑定手机状态:绑定手机 绑定邮箱状态:无 实名认证状态:有
{
factoryMeta: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindNothingAndIdenAuth,
riskLevel: _defaultRiskLevel,
},
rules: Rules{
_telIsNotBound, _mailIsNotBound, _idenIsAuthed,
}},
// 绑定手机状态:绑定手机,且天域认定为高风险 邮箱绑定状态any 实名认证状态:无
{
factoryMeta: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindTelHighRiskAndIdenUnauth,
riskLevel: _defaultRiskLevel,
},
rules: Rules{
_telIsBound, _telIsHighRisk, _idenIsNotAuthed,
}},
}
}
func (s *Service) getJudgementInfo(c context.Context, mid int64, ip string) (judgementInfo *JudgementInfo, err error) {
return NewJudgementInfo(c, s, mid, ip), nil
}
func (s *Service) getRuleFunc(rule Rule) (ruleFunc RuleFunc, err error) {
ruleFunc, ok := ruleToFuncMaps[rule]
if !ok {
err = ecode.SpyRuleNotExist
return
}
return
}
func (s *Service) iterRules(info *JudgementInfo, rules Rules) (state IterState, err error) {
var (
counter int
ruleFunc RuleFunc
result bool
)
for _, rule := range rules {
if ruleFunc, err = s.getRuleFunc(rule); err != nil {
return
}
if result, err = ruleFunc(info); err != nil {
return
}
if !result {
log.Info("s.iterRules mid(%d) rules(%v) counter(%d) state(%d)", info.mid, rules, counter, IterFail)
return IterFail, nil
}
counter++
}
log.Info("s.iterRules mid(%d) rules(%v) counter(%d) state(%d)", info.mid, rules, counter, IterSuccess)
return IterSuccess, nil
}
func (s *Service) getBaseScoreFactor(info *JudgementInfo) (meta FactoryMeta, err error) {
var (
ruleMap RuleMap
state IterState
)
for _, ruleMap = range s.getRulesMap() {
if state, err = s.iterRules(info, ruleMap.rules); err != nil {
log.Error("s.iterRules(%v, %v) err(%v)", info, ruleMap.rules, err)
return
}
if state == IterSuccess {
return ruleMap.factoryMeta, nil
}
}
err = ecode.SpyRulesNotMatch
return
}
func telIsBound(info *JudgementInfo) (result bool, err error) {
var (
auditInfo *model.AuditInfo
)
if auditInfo, err = info.getAuditInfo(); err != nil {
return
}
return auditInfo.BindTel, nil
}
func telIsNotBound(info *JudgementInfo) (result bool, err error) {
var (
auditInfo *model.AuditInfo
)
if auditInfo, err = info.getAuditInfo(); err != nil {
return
}
return !auditInfo.BindTel, nil
}
func telIsLowRisk(info *JudgementInfo) (result bool, err error) {
var (
telRiskInfo *model.TelRiskInfo
)
if telRiskInfo, err = info.getTelRiskInfo(); err != nil {
return
}
if telRiskInfo.RestoreHistory != nil || telRiskInfo.UnicomGiftState == 1 {
return true, nil
}
return telRiskInfo.TelRiskLevel == dao.TelRiskLevelLow, nil
}
func telIsMediumRisk(info *JudgementInfo) (result bool, err error) {
var (
telRiskInfo *model.TelRiskInfo
)
if telRiskInfo, err = info.getTelRiskInfo(); err != nil {
return
}
if telRiskInfo.RestoreHistory != nil || telRiskInfo.UnicomGiftState == 1 {
return false, nil
}
return telRiskInfo.TelRiskLevel == dao.TelRiskLevelMedium, nil
}
func telIsHighRisk(info *JudgementInfo) (result bool, err error) {
var (
telRiskInfo *model.TelRiskInfo
)
if telRiskInfo, err = info.getTelRiskInfo(); err != nil {
return
}
if telRiskInfo.RestoreHistory != nil || telRiskInfo.UnicomGiftState == 1 {
return false, nil
}
return telRiskInfo.TelRiskLevel == dao.TelRiskLevelHigh, nil
}
func telIsUnknownRisk(info *JudgementInfo) (result bool, err error) {
var (
telRiskInfo *model.TelRiskInfo
)
if telRiskInfo, err = info.getTelRiskInfo(); err != nil {
return
}
if telRiskInfo.RestoreHistory != nil || telRiskInfo.UnicomGiftState == 1 {
return false, nil
}
return telRiskInfo.TelRiskLevel == dao.TelRiskLevelUnknown, nil
}
func mailIsBound(info *JudgementInfo) (result bool, err error) {
var (
auditInfo *model.AuditInfo
)
if auditInfo, err = info.getAuditInfo(); err != nil {
return
}
return auditInfo.BindMail, nil
}
func mailIsNotBound(info *JudgementInfo) (result bool, err error) {
var (
auditInfo *model.AuditInfo
)
if auditInfo, err = info.getAuditInfo(); err != nil {
return
}
return !auditInfo.BindMail, nil
}
func idenIsNotAuthed(info *JudgementInfo) (result bool, err error) {
var (
profileInfo *model.ProfileInfo
)
if profileInfo, err = info.getProfileInfo(); err != nil {
return
}
return profileInfo.Identification == 0, nil
}
func idenIsAuthed(info *JudgementInfo) (result bool, err error) {
var (
profileInfo *model.ProfileInfo
)
if profileInfo, err = info.getProfileInfo(); err != nil {
return
}
return profileInfo.Identification == 1, nil
}

View File

@ -0,0 +1,763 @@
package service
import (
"context"
"errors"
"fmt"
"reflect"
"testing"
"go-common/app/service/main/spy/conf"
"go-common/app/service/main/spy/dao"
"go-common/app/service/main/spy/model"
"go-common/library/ecode"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceNewJudgementInfo(t *testing.T) {
convey.Convey("NewJudgementInfo", t, func(ctx convey.C) {
var (
s = &Service{}
c = context.Background()
mid = int64(0)
ip = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := NewJudgementInfo(c, s, mid, ip)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestServicegetAuditInfo(t *testing.T) {
var (
mid = int64(0)
ip = ""
ji = NewJudgementInfo(context.TODO(), s, mid, ip)
auditInfo = &model.AuditInfo{
Mid: mid,
BindTel: true,
BindMail: false,
}
)
convey.Convey("getAuditInfo", t, func(ctx convey.C) {
var testCases = []struct {
jiAuditInfo *model.AuditInfo
daoAuditInfo *model.AuditInfo
expectAuditInfo *model.AuditInfo
}{
{
jiAuditInfo: auditInfo,
daoAuditInfo: nil,
expectAuditInfo: auditInfo,
},
{
jiAuditInfo: nil,
daoAuditInfo: auditInfo,
expectAuditInfo: auditInfo,
},
{
jiAuditInfo: nil,
daoAuditInfo: nil,
expectAuditInfo: nil,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d", idx), func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "AuditInfo", func(_ *dao.Dao, _ context.Context, _ int64, _ string) (*model.AuditInfo, error) {
if testCase.daoAuditInfo == nil {
return nil, errors.New("s.dao.AuditInfo error")
}
return testCase.daoAuditInfo, nil
})
ji.auditInfo = testCase.jiAuditInfo
ai, err := ji.getAuditInfo()
if testCase.expectAuditInfo == nil {
ctx.So(err, convey.ShouldBeError)
ctx.So(ai, convey.ShouldBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ai, convey.ShouldEqual, testCase.expectAuditInfo)
}
})
}
})
}
func TestServicegetProfileInfo(t *testing.T) {
var (
mid = int64(0)
ip = ""
ji = NewJudgementInfo(context.TODO(), s, mid, ip)
profileInfo = &model.ProfileInfo{
Mid: mid,
Identification: 0,
}
)
convey.Convey("getProfileInfo", t, func(ctx convey.C) {
var testCases = []struct {
jiProfileInfo *model.ProfileInfo
daoProfileInfo *model.ProfileInfo
expectProfileInfo *model.ProfileInfo
}{
{
jiProfileInfo: profileInfo,
daoProfileInfo: nil,
expectProfileInfo: profileInfo,
},
{
jiProfileInfo: nil,
daoProfileInfo: profileInfo,
expectProfileInfo: profileInfo,
},
{
jiProfileInfo: nil,
daoProfileInfo: nil,
expectProfileInfo: nil,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d", idx), func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "ProfileInfo", func(_ *dao.Dao, _ context.Context, _ int64, _ string) (*model.ProfileInfo, error) {
if testCase.daoProfileInfo == nil {
return nil, errors.New("s.dao.ProfileInfo error")
}
return testCase.daoProfileInfo, nil
})
ji.profileInfo = testCase.jiProfileInfo
pi, err := ji.getProfileInfo()
if testCase.expectProfileInfo == nil {
ctx.So(err, convey.ShouldBeError)
ctx.So(pi, convey.ShouldBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
ctx.So(pi, convey.ShouldEqual, testCase.expectProfileInfo)
}
})
}
})
}
func TestServicegetTelRiskInfo(t *testing.T) {
var (
mid = int64(0)
ip = ""
ji = NewJudgementInfo(context.TODO(), s, mid, ip)
telRiskLevel = int8(1)
restoreEventHistory = &model.UserEventHistory{
Mid: mid,
EventID: 1024,
}
telRiskInfo = &model.TelRiskInfo{
TelRiskLevel: telRiskLevel,
RestoreHistory: restoreEventHistory,
}
)
convey.Convey("getTelRiskInfo", t, func(ctx convey.C) {
var testCases = []struct {
jiTelRiskInfo *model.TelRiskInfo
daoTelRiskLevel int8
daoRestoreEventHistory *model.UserEventHistory
expectTelRiskInfo *model.TelRiskInfo
}{
{
jiTelRiskInfo: telRiskInfo,
daoTelRiskLevel: int8(0),
daoRestoreEventHistory: nil,
expectTelRiskInfo: telRiskInfo,
},
{
jiTelRiskInfo: nil,
daoTelRiskLevel: telRiskLevel,
daoRestoreEventHistory: restoreEventHistory,
expectTelRiskInfo: telRiskInfo,
},
{
jiTelRiskInfo: nil,
daoTelRiskLevel: int8(0),
daoRestoreEventHistory: nil,
expectTelRiskInfo: nil,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d", idx), func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "TelRiskLevel", func(_ *dao.Dao, _ context.Context, _ int64) (int8, error) {
return testCase.daoTelRiskLevel, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "Event", func(_ *dao.Dao, _ context.Context, _ string) (*model.Event, error) {
return &model.Event{
ID: mid,
}, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "EventHistoryByMidAndEvent", func(_ *dao.Dao, _ context.Context, _ int64, _ int64) (*model.UserEventHistory, error) {
if testCase.daoRestoreEventHistory == nil {
return nil, errors.New("s.dao.EventHistoryByMidAndEvent error")
}
return testCase.daoRestoreEventHistory, nil
})
ji.telRiskInfo = testCase.jiTelRiskInfo
tri, err := ji.getTelRiskInfo()
if testCase.expectTelRiskInfo == nil {
ctx.So(err, convey.ShouldBeError)
ctx.So(tri, convey.ShouldBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
ctx.So(tri, convey.ShouldResemble, testCase.expectTelRiskInfo)
}
})
}
})
}
func TestServicegetRulesMap(t *testing.T) {
convey.Convey("getRulesMap", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := s.getRulesMap()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestServicegetJudgementInfo(t *testing.T) {
convey.Convey("getJudgementInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
ip = ""
)
convey.Convey("getJudgementInfo", func(ctx convey.C) {
ji, err := s.getJudgementInfo(c, mid, ip)
ctx.So(ji, convey.ShouldNotBeNil)
ctx.So(ji.auditInfo, convey.ShouldBeNil)
ctx.So(ji.profileInfo, convey.ShouldBeNil)
ctx.So(ji.telRiskInfo, convey.ShouldBeNil)
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestServicegetRuleFunc(t *testing.T) {
convey.Convey("getRuleFunc", t, func(ctx convey.C) {
var testCases = []struct {
rule Rule
expectedResp RuleFunc
}{
{
rule: _telIsBound,
expectedResp: telIsBound,
},
{
rule: "Anything",
expectedResp: nil,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d..,", idx), func(ctx convey.C) {
ruleFunc, err := s.getRuleFunc(testCase.rule)
if testCase.expectedResp == nil {
ctx.So(err, convey.ShouldBeError, ecode.SpyRuleNotExist)
ctx.So(ruleFunc, convey.ShouldBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ruleFunc, convey.ShouldEqual, testCase.expectedResp)
}
})
}
})
}
func TestServiceiterRules(t *testing.T) {
var (
rules = Rules{
_telIsBound, _mailIsBound,
}
)
convey.Convey("iterRules", t, func(ctx convey.C) {
var testCases = []struct {
judgementInfo *JudgementInfo
expectRes IterState
}{
{
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindTel: true,
BindMail: true,
},
},
expectRes: IterSuccess,
},
{
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindTel: true,
BindMail: false,
},
},
expectRes: IterFail,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
state, err := s.iterRules(testCase.judgementInfo, rules)
ctx.So(err, convey.ShouldBeNil)
ctx.So(state, convey.ShouldEqual, testCase.expectRes)
})
}
})
}
func TestServicegetBaseScoreFactor(t *testing.T) {
convey.Convey("getBaseScoreFactor", t, func(ctx convey.C) {
var (
testCases = []struct {
judgementInfo *JudgementInfo
expectRest FactoryMeta
}{
{
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindTel: false,
BindMail: true,
},
telRiskInfo: &model.TelRiskInfo{
RestoreHistory: &model.UserEventHistory{
Mid: int64(0),
},
},
},
expectRest: FactoryMeta{
serviceName: _defaultService,
eventName: conf.Conf.Property.Event.BindMailAndIdenUnknown,
riskLevel: _defaultRiskLevel,
},
},
{
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindTel: false,
BindMail: false,
},
profileInfo: &model.ProfileInfo{
Identification: 1,
},
telRiskInfo: &model.TelRiskInfo{
RestoreHistory: &model.UserEventHistory{
Mid: int64(0),
},
},
},
expectRest: FactoryMeta{},
},
}
)
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
meta, err := s.getBaseScoreFactor(testCase.judgementInfo)
if testCase.expectRest == (FactoryMeta{}) {
ctx.So(err, convey.ShouldBeError, ecode.SpyRulesNotMatch)
ctx.So(meta, convey.ShouldResemble, FactoryMeta{})
} else {
ctx.So(err, convey.ShouldBeNil)
ctx.So(meta, convey.ShouldResemble, testCase.expectRest)
}
})
}
})
}
func TestServicetelIsBound(t *testing.T) {
convey.Convey("telIsBound", t, func(ctx convey.C) {
var testCases = []struct {
judgementInfo *JudgementInfo
expectResp bool
}{
{
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindTel: true,
},
},
expectResp: true,
}, {
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindTel: false,
},
},
expectResp: false,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
result, err := telIsBound(testCase.judgementInfo)
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldEqual, testCase.expectResp)
})
}
})
}
func TestServicetelIsNotBound(t *testing.T) {
convey.Convey("telIsNotBound", t, func(ctx convey.C) {
var testCases = []struct {
judgementInfo *JudgementInfo
expectResp bool
}{
{
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindTel: true,
},
},
expectResp: false,
}, {
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindTel: false,
},
},
expectResp: true,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
result, err := telIsNotBound(testCase.judgementInfo)
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldEqual, testCase.expectResp)
})
}
})
}
func TestServicetelIsLowRisk(t *testing.T) {
convey.Convey("telIsLowRisk", t, func(ctx convey.C) {
var testCases = []struct {
judgementInfo *JudgementInfo
expectResp bool
}{
{
judgementInfo: &JudgementInfo{
telRiskInfo: &model.TelRiskInfo{
TelRiskLevel: dao.TelRiskLevelLow,
RestoreHistory: nil,
},
},
expectResp: true,
},
{
judgementInfo: &JudgementInfo{
telRiskInfo: &model.TelRiskInfo{
TelRiskLevel: dao.TelRiskLevelHigh,
RestoreHistory: &model.UserEventHistory{
Mid: int64(0),
},
},
},
expectResp: true,
},
{
judgementInfo: &JudgementInfo{
telRiskInfo: &model.TelRiskInfo{
TelRiskLevel: dao.TelRiskLevelHigh,
RestoreHistory: nil,
},
},
expectResp: false,
},
{
judgementInfo: &JudgementInfo{
telRiskInfo: &model.TelRiskInfo{
TelRiskLevel: dao.TelRiskLevelHigh,
RestoreHistory: nil,
UnicomGiftState: 1,
},
},
expectResp: true,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
result, err := telIsLowRisk(testCase.judgementInfo)
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldEqual, testCase.expectResp)
})
}
})
}
func TestServicetelIsMediumRisk(t *testing.T) {
convey.Convey("telIsMediumRisk", t, func(ctx convey.C) {
var testCases = []struct {
judgementInfo *JudgementInfo
expectResp bool
}{
{
judgementInfo: &JudgementInfo{
telRiskInfo: &model.TelRiskInfo{
TelRiskLevel: dao.TelRiskLevelMedium,
RestoreHistory: nil,
},
},
expectResp: true,
},
{
judgementInfo: &JudgementInfo{
telRiskInfo: &model.TelRiskInfo{
TelRiskLevel: dao.TelRiskLevelMedium,
RestoreHistory: &model.UserEventHistory{
Mid: int64(0),
},
},
},
expectResp: false,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
result, err := telIsMediumRisk(testCase.judgementInfo)
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldEqual, testCase.expectResp)
})
}
})
}
func TestServicetelIsHighRisk(t *testing.T) {
convey.Convey("telIsHighRisk", t, func(ctx convey.C) {
var testCases = []struct {
judgementInfo *JudgementInfo
expectResp bool
}{
{
judgementInfo: &JudgementInfo{
telRiskInfo: &model.TelRiskInfo{
TelRiskLevel: dao.TelRiskLevelHigh,
RestoreHistory: nil,
},
},
expectResp: true,
},
{
judgementInfo: &JudgementInfo{
telRiskInfo: &model.TelRiskInfo{
TelRiskLevel: dao.TelRiskLevelHigh,
RestoreHistory: nil,
UnicomGiftState: 1,
},
},
expectResp: false,
},
{
judgementInfo: &JudgementInfo{
telRiskInfo: &model.TelRiskInfo{
TelRiskLevel: dao.TelRiskLevelMedium,
},
},
expectResp: false,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
result, err := telIsHighRisk(testCase.judgementInfo)
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldEqual, testCase.expectResp)
})
}
})
}
func TestServicetelIsUnknownRisk(t *testing.T) {
convey.Convey("telIsUnknownRisk", t, func(ctx convey.C) {
var testCases = []struct {
judgementInfo *JudgementInfo
expectResp bool
}{
{
judgementInfo: &JudgementInfo{
telRiskInfo: &model.TelRiskInfo{
TelRiskLevel: dao.TelRiskLevelUnknown,
RestoreHistory: nil,
},
},
expectResp: true,
},
{
judgementInfo: &JudgementInfo{
telRiskInfo: &model.TelRiskInfo{
TelRiskLevel: dao.TelRiskLevelMedium,
},
},
expectResp: false,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
result, err := telIsUnknownRisk(testCase.judgementInfo)
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldEqual, testCase.expectResp)
})
}
})
}
func TestServicemailIsBound(t *testing.T) {
convey.Convey("mailIsBound", t, func(ctx convey.C) {
var testCases = []struct {
judgementInfo *JudgementInfo
expectResp bool
}{
{
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindMail: true,
},
},
expectResp: true,
}, {
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindMail: false,
},
},
expectResp: false,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
result, err := mailIsBound(testCase.judgementInfo)
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldEqual, testCase.expectResp)
})
}
})
}
func TestServicemailIsNotBound(t *testing.T) {
convey.Convey("mailIsNotBound", t, func(ctx convey.C) {
var testCases = []struct {
judgementInfo *JudgementInfo
expectResp bool
}{
{
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindMail: true,
},
},
expectResp: false,
}, {
judgementInfo: &JudgementInfo{
auditInfo: &model.AuditInfo{
BindMail: false,
},
},
expectResp: true,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
result, err := mailIsNotBound(testCase.judgementInfo)
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldEqual, testCase.expectResp)
})
}
})
}
func TestServiceidenIsNotAuthed(t *testing.T) {
convey.Convey("idenIsNotAuthed", t, func(ctx convey.C) {
var testCases = []struct {
judgementInfo *JudgementInfo
expectResp bool
}{
{
judgementInfo: &JudgementInfo{
profileInfo: &model.ProfileInfo{
Identification: 0,
},
},
expectResp: true,
}, {
judgementInfo: &JudgementInfo{
profileInfo: &model.ProfileInfo{
Identification: 1,
},
},
expectResp: false,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
result, err := idenIsNotAuthed(testCase.judgementInfo)
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldEqual, testCase.expectResp)
})
}
})
}
func TestServiceidenIsAuthed(t *testing.T) {
convey.Convey("idenIsAuthed", t, func(ctx convey.C) {
var testCases = []struct {
judgementInfo *JudgementInfo
expectResp bool
}{
{
judgementInfo: &JudgementInfo{
profileInfo: &model.ProfileInfo{
Identification: 0,
},
},
expectResp: false,
}, {
judgementInfo: &JudgementInfo{
profileInfo: &model.ProfileInfo{
Identification: 1,
},
},
expectResp: true,
},
}
for idx, testCase := range testCases {
ctx.Convey(fmt.Sprintf("Iterating Case%d...", idx), func(ctx convey.C) {
result, err := idenIsAuthed(testCase.judgementInfo)
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldEqual, testCase.expectResp)
})
}
})
}

View File

@ -0,0 +1,253 @@
package service
import (
"context"
"errors"
"strconv"
"time"
accrpc "go-common/app/service/main/account/rpc/client"
"go-common/app/service/main/spy/conf"
"go-common/app/service/main/spy/dao"
"go-common/app/service/main/spy/model"
"go-common/library/log"
"go-common/library/stat/prom"
)
const (
_score = 100
)
// Service biz service def.
type Service struct {
c *conf.Config
dao *dao.Dao
missch chan func()
scorech chan func()
infomissch chan func()
spyConfig map[string]interface{}
configLoadTick time.Duration
promBaseScore *prom.Prom
promEventScore *prom.Prom
promBlockInfo *prom.Prom
accRPC *accrpc.Service3
allEventName map[int64]string
loadEventTick time.Duration
}
// New new a Service and return.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
missch: make(chan func(), 10240),
scorech: make(chan func(), 10240),
infomissch: make(chan func(), 10240),
spyConfig: make(map[string]interface{}),
configLoadTick: time.Duration(c.Property.ConfigLoadTick),
promBaseScore: prom.New().WithCounter("spy_basescore", []string{"name"}),
promEventScore: prom.New().WithCounter("spy_eventscore", []string{"name"}),
promBlockInfo: prom.New().WithCounter("spy_block_info", []string{"name"}),
accRPC: accrpc.New3(c.RPC.Account),
allEventName: make(map[int64]string),
loadEventTick: time.Duration(c.Property.LoadEventTick),
}
if err := s.loadSystemConfig(); err != nil {
panic(err)
}
s.loadeventname()
go s.missproc()
go s.infomissproc()
go s.loadconfigproc()
go s.loadeventproc()
go s.updatescoreproc()
return s
}
// Ping check dao health.
func (s *Service) Ping(c context.Context) (err error) {
return s.dao.Ping(c)
}
// Close close all dao.
func (s *Service) Close() {
s.dao.Close()
}
func (s *Service) missproc() {
defer func() {
if x := recover(); x != nil {
log.Error("service.missproc panic(%v)", x)
go s.missproc()
log.Info("service.missproc recover")
}
}()
for {
f := <-s.missch
f()
}
}
func (s *Service) mission(f func()) {
defer func() {
if x := recover(); x != nil {
log.Error("service.mission panic(%v)", x)
}
}()
select {
case s.missch <- f:
default:
log.Error("service.missproc chan full")
}
}
func (s *Service) updatescoreproc() {
defer func() {
if x := recover(); x != nil {
log.Error("service.updatescoreproc panic(%v)", x)
go s.updatescoreproc()
log.Info("service.updatescoreproc recover")
}
}()
for {
f := <-s.scorech
f()
}
}
func (s *Service) updatescore(f func()) {
defer func() {
if x := recover(); x != nil {
log.Error("service.updatescore panic(%v)", x)
}
}()
select {
case s.scorech <- f:
default:
log.Error("service.updatescore chan full")
}
}
func (s *Service) infomissproc() {
defer func() {
if x := recover(); x != nil {
log.Error("service.infomissproc panic(%v)", x)
go s.infomissproc()
log.Info("service.infomissproc recover")
}
}()
for {
f := <-s.infomissch
f()
}
}
func (s *Service) infomission(f func()) {
defer func() {
if x := recover(); x != nil {
log.Error("service.infomission panic(%v)", x)
}
}()
select {
case s.infomissch <- f:
default:
log.Error("service.infomissch chan full")
}
}
func (s *Service) loadconfigproc() {
defer func() {
if x := recover(); x != nil {
log.Error("service.loadconfig panic(%v)", x)
}
}()
for {
time.Sleep(s.configLoadTick)
s.loadSystemConfig()
}
}
func (s *Service) loadSystemConfig() (err error) {
var (
cdb map[string]string
)
cdb, err = s.dao.Configs(context.TODO())
if err != nil {
log.Error("sys config db get data err(%v)", err)
return
}
if len(cdb) == 0 {
err = errors.New("sys config no data")
return
}
cs := make(map[string]interface{}, len(cdb))
for k, v := range cdb {
switch k {
case model.LimitBlockCount:
t, err1 := strconv.ParseInt(v, 10, 64)
if err1 != nil {
log.Error("sys config err(%s,%v,%v)", model.LimitBlockCount, t, err1)
err = err1
return
}
cs[k] = t
case model.LessBlockScore:
tmp, err1 := strconv.ParseInt(v, 10, 8)
if err1 != nil {
log.Error("sys config err(%s,%v,%v)", model.LessBlockScore, tmp, err1)
err = err1
return
}
cs[k] = int8(tmp)
case model.AutoBlock:
tmp, err1 := strconv.ParseInt(v, 10, 8)
if err1 != nil {
log.Error("sys config err(%s,%v,%v)", model.AutoBlock, tmp, err1)
err = err1
return
}
cs[k] = int8(tmp)
default:
cs[k] = v
}
}
s.spyConfig = cs
log.Info("loadSystemConfig success(%v)", cs)
return
}
//Config get config.
func (s *Service) Config(key string) (interface{}, bool) {
if s.spyConfig == nil {
return nil, false
}
v, ok := s.spyConfig[key]
return v, ok
}
func (s *Service) loadeventname() (err error) {
var (
c = context.Background()
es []*model.Event
)
es, err = s.dao.AllEvent(c)
if err != nil {
log.Error("loadeventname allevent error(%v)", err)
return
}
tmp := make(map[int64]string, len(es))
for _, e := range es {
tmp[e.ID] = e.NickName
}
s.allEventName = tmp
log.Info("loadeventname (%v) load success", tmp)
return
}
func (s *Service) loadeventproc() {
for {
time.Sleep(s.loadEventTick)
s.loadeventname()
}
}

View File

@ -0,0 +1,195 @@
package service
import (
"context"
"flag"
"fmt"
"os"
"path/filepath"
"testing"
"time"
"go-common/app/service/main/spy/conf"
"go-common/app/service/main/spy/model"
"go-common/library/cache/redis"
"go-common/library/log"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
c = context.TODO()
// 35858 : bind nothing
// 22333 : bind mail only
// 46333 : bind both
// 27515232 : bind both
mids = []int64{27515232}
)
func TestMain(m *testing.M) {
flag.Parse()
var err error
if err = conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
if s == nil {
s = New(conf.Conf)
}
os.Exit(m.Run())
}
func TestDelCache(t *testing.T) {
var err error
for _, mid := range mids {
if err = s.dao.DelInfoCache(c, mid); err != nil {
t.Fatal(err)
}
}
}
func TestUserInfo(t *testing.T) {
var (
ip = "127.0.0.1"
err error
ui *model.UserInfo
)
for _, mid := range mids {
if ui, err = s.UserInfo(c, mid, ip); err != nil {
t.Fatal(err)
}
if ui == nil {
t.Fatal()
}
t.Logf("userinfo (%+v)", ui)
}
}
func TestHandleEvent(t *testing.T) {
var (
arg struct {
Test string
}
err error
ui *model.UserInfo
preEventScore int8
preBaseScore int8
fac *model.Factor
)
arg.Test = "test arg"
for _, mid := range mids {
var fakeEventMsg = &model.EventMessage{
IP: "127.0.0.1",
Service: "spy_service",
Event: "bind_nothing",
ActiveMid: mid,
TargetMid: mid,
Result: "test_result",
Effect: "test_effect",
RiskLevel: 1,
}
fakeEventMsg.Args = arg
if ui, err = s.UserInfo(c, fakeEventMsg.ActiveMid, fakeEventMsg.IP); err != nil {
t.Fatal(err)
}
if ui == nil {
t.Fatal()
}
preBaseScore = ui.BaseScore
preEventScore = ui.EventScore
if err = s.HandleEvent(c, fakeEventMsg); err != nil {
t.Fatal(err)
}
if ui, err = s.UserInfo(c, fakeEventMsg.ActiveMid, fakeEventMsg.IP); err != nil {
t.Fatal(err)
}
if ui.State == model.StateBlock {
continue
}
if ui.BaseScore != preBaseScore {
t.Fatal()
}
if fac, err = s.factor(c, fakeEventMsg.Service, fakeEventMsg.Event, 1); err != nil {
t.Fatal(err)
}
if ui.EventScore != int8(float64(preEventScore)*fac.FactorVal) {
t.Fatal()
}
if ui.Score != int8(float64(ui.BaseScore)*float64(ui.EventScore)/float64(100)) {
t.Fatal()
}
if err = s.dao.DelInfoCache(c, mid); err != nil {
t.Fatal(err)
}
}
time.Sleep(time.Second * 1)
}
func CleanCache() {
pool := redis.NewPool(conf.Conf.Redis.Config)
pool.Get(c).Do("FLUSHDB")
}
func init() {
dir, _ := filepath.Abs("../cmd/spy-service-test.toml")
flag.Set("conf", dir)
conf.Init()
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() { CleanCache() })
f(s)
}
}
func Test_LoadSystemConfig(t *testing.T) {
Convey("Test_LoadSystemConfig had data", t, WithService(func(s *Service) {
fmt.Println(s.spyConfig)
So(s.spyConfig, ShouldContainKey, model.LimitBlockCount)
So(s.spyConfig, ShouldContainKey, model.LessBlockScore)
So(s.spyConfig, ShouldContainKey, model.AutoBlock)
}))
}
// go test -test.v -test.run TestStatList
func TestStatList(t *testing.T) {
var (
mid int64 = 1
id int64 = 1
)
Convey("TestStatList ", t, WithService(func(s *Service) {
stat, err := s.StatByID(c, mid, id)
So(err, ShouldBeNil)
fmt.Println("stat", stat)
}))
}
// go test -test.v -test.run TestTelLevel
func TestTelLevel(t *testing.T) {
var (
mid int64 = 15555180
)
Convey("TestTelLevel no err", t, WithService(func(s *Service) {
level, err := s.TelRiskLevel(c, mid, "127.0.0.1")
fmt.Println("level", level)
So(err, ShouldBeNil)
}))
}
// go test -test.v -test.run TestTelLevel
func TestService_StatByIDGroupEvent(t *testing.T) {
var (
mid int64 = 7455
)
Convey("StatByIDGroupEvent no err", t, WithService(func(s *Service) {
res, err := s.StatByIDGroupEvent(c, mid, 0)
So(res, ShouldNotBeNil)
So(err, ShouldBeNil)
}))
}

View File

@ -0,0 +1,682 @@
package service
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"time"
"go-common/app/service/main/spy/conf"
"go-common/app/service/main/spy/dao"
"go-common/app/service/main/spy/model"
spy "go-common/app/service/main/spy/model"
"go-common/library/database/sql"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/ip"
"go-common/library/net/metadata"
"github.com/pkg/errors"
)
// HandleEvent handle spy-event.
func (s *Service) HandleEvent(c context.Context, eventMsg *model.EventMessage) (err error) {
var (
factor *model.Factor
mid = eventMsg.ActiveMid
)
ui, err := s.UserInfo(c, mid, ip.InternalIP())
if err != nil {
log.Error("s.UserInfo(%d) err(%v)", mid, err)
return
}
// if blocked already , return
// if ui.State == model.StateBlock {
// return
// }
// get factor by servieName , eventName , riskLevel
if factor, err = s.factor(c, eventMsg.Service, eventMsg.Event, eventMsg.RiskLevel); err != nil {
log.Error("s.factor(%s, %s, %d) error(%v)", eventMsg.Service, eventMsg.Event, eventMsg.RiskLevel, err)
return
}
s.promEventScore.Incr("change")
// mark eventScore decrease
if factor.FactorVal < 1.0 {
s.promEventScore.Incr("decrease")
}
// calc all score
ui.EventScore = s.calcFactorScore(ui.EventScore, factor)
ui.Score = s.calcScore(ui.BaseScore, ui.EventScore)
if err = s.updateEventInfo(c, ui, factor, eventMsg); err != nil {
log.Error("s.updateEventInfo(%v, %v, %v) error(%v)", ui, factor, eventMsg, err)
return
}
s.updateInfoCache(c, ui)
// check punishment.
_, err = s.BlockFilter(c, ui)
if err != nil {
log.Error("s.BlockFilter(%v) error(%v)", ui, err)
return
}
return
}
func (s *Service) updateEventInfo(c context.Context, ui *model.UserInfo, factor *model.Factor, eventMsg *model.EventMessage) (err error) {
var (
tx *sql.Tx
)
if tx, err = s.dao.BeginTran(c); err != nil {
log.Error("s.dao.BeginTran() err(%v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("tx.Rollback() error(%v)", err1)
}
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
}
}()
// update info.
if err = s.dao.TxUpdateInfo(c, tx, ui); err != nil {
log.Error("s.dao.UpsertInfo(%v) error(%v)", ui, err)
return
}
if err = s.txAddHistory(c, tx, ui, factor, eventMsg); err != nil {
log.Error("s.addHistory(%v, %v, %v) error(%v)", ui, factor, eventMsg, err)
return
}
s.dao.PubScoreChange(c, ui.Mid, &model.ScoreChange{
Mid: ui.Mid,
Score: ui.Score,
TS: time.Now().Unix(),
Reason: eventMsg.Service,
RiskLevel: eventMsg.RiskLevel,
})
return
}
// factor get facory by serviceName , eventName , riskLevel.
func (s *Service) factor(c context.Context, serviceName, eventName string, riskLevel int8) (factor *model.Factor, err error) {
var (
event *model.Event
)
if event, err = s.dao.Event(c, eventName); err != nil {
log.Error("s.dao.Event(%s) error(%v)", eventName, err)
return
}
if event == nil {
log.Error("event(%s) not support", eventName)
err = ecode.SpyEventNotExist
return
}
if factor, err = s.dao.Factor(c, event.ServiceID, event.ID, riskLevel); err != nil {
log.Error("s.dao.Factor(%d, %d, %d) error(%v)", event.ServiceID, event.ID, riskLevel, err)
return
}
if factor == nil {
log.Warn("factor(service=%d,event=%d,risklevel=%d) not support", event.ServiceID, event.ID, riskLevel)
err = ecode.SpyFactorNotExist
return
}
return
}
// UserInfo get UserInfo by mid , from cache or db or generate.
func (s *Service) UserInfo(c context.Context, mid int64, ip string) (ui *model.UserInfo, err error) {
ui, err = s.userInfo(c, mid)
if ui != nil {
return
}
// user info not generated , so let's do it.
if ui, err = s.initUserInfo(c, mid, ip); err != nil {
log.Error("s.generateUserInfo(%d) error(%v)", mid, err)
return
}
return
}
// UserInfoAsyn get UserInfo by mid , from cache or db or asyn generate.
func (s *Service) UserInfoAsyn(c context.Context, mid int64) (ui *model.UserInfo, err error) {
ui, err = s.userInfo(c, mid)
if ui != nil {
return
}
ip := metadata.String(c, metadata.RemoteIP)
s.infomission(func() {
if _, err1 := s.initUserInfo(context.TODO(), mid, ip); err1 != nil {
log.Error("s.generateUserInfo(%d) error(%v)", mid, err1)
return
}
})
return
}
// UserInfo get UserInfo by mid , from cache or db.
func (s *Service) userInfo(c context.Context, mid int64) (ui *model.UserInfo, err error) {
var cacheFlag = true
// get info from cache.
if ui, err = s.dao.UserInfoCache(c, mid); err != nil {
cacheFlag = false
err = nil
log.Error("s.dao.InfoCache(%d) error(%v)", mid, err)
}
// return if cache exist.
if ui != nil {
return
}
// get info from db.
if ui, err = s.dao.UserInfo(c, mid); err != nil {
log.Error("s.dao.Info(%d) error(%v)", mid, err)
return
}
if ui != nil {
// reload to cache
if cacheFlag {
s.updateInfoCache(c, ui)
}
}
return
}
// Info returns user info.
func (s *Service) Info(c context.Context, mid int64) (ui *model.UserInfo, err error){
ui, err = s.UserInfoAsyn(c, mid)
if err != nil {
return
}
if ui == nil {
// asyn init user score , return def score.
ui = &model.UserInfo{Mid: mid, Score: model.SpyInitScore}
}
return ui, nil
}
// initUserInfo .
func (s *Service) initUserInfo(c context.Context, mid int64, ip string) (ui *model.UserInfo, err error) {
var (
tx *sql.Tx
// init default info
fakeFactor = &model.Factor{
NickName: "initialization",
ServiceID: -1,
EventID: conf.Conf.Property.Event.InitEventID,
GroupID: -1,
RiskLevel: 1,
FactorVal: 1.0,
}
fakeEventMsg = &model.EventMessage{
IP: "127.0.0.1",
ActiveMid: mid,
TargetMid: mid,
Effect: "initialization",
RiskLevel: 1,
}
)
// start generate logic.
ui = &model.UserInfo{
Mid: mid,
EventScore: conf.Conf.Property.Score.EventInit,
State: model.StateNormal,
}
if ui.BaseScore, err = s.getBaseScore(c, mid, ip); err != nil {
log.Error("s.calcBaseScore(%d, %s) error(%v)", mid, ip, err)
return
}
ui.Score = s.calcScore(ui.BaseScore, ui.EventScore)
// add new info into db.
if tx, err = s.dao.BeginTran(c); err != nil {
log.Error("s.dao.BeginTran() err(%v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("tx.Rollback() error(%v)", err1)
}
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
}
}()
if ui.ID, err = s.dao.TxAddInfo(c, tx, ui); err != nil {
log.Error("s.userDao.NewInfo(%d, %v) error(%v)", mid, ui, err)
return
}
if err = s.txAddHistory(c, tx, ui, fakeFactor, fakeEventMsg); err != nil {
log.Error("s.addHistory(%v, %v, %v) error(%v)", ui, fakeFactor, fakeEventMsg, err)
return
}
s.updateInfoCache(c, ui)
s.dao.PubScoreChange(c, mid, &model.ScoreChange{
Mid: mid,
Score: ui.Score,
TS: time.Now().Unix(),
})
return
}
func (s *Service) calcFactorScore(preScore int8, factor *model.Factor) (score int8) {
return int8(float64(preScore) * factor.FactorVal)
}
// calc real score.
func (s *Service) calcScore(baseScore, eventScore int8) (score int8) {
return int8(float64(baseScore) * float64(eventScore) / float64(_score))
}
// getBaseScore get base score.
func (s *Service) getBaseScore(c context.Context, mid int64, ip string) (score int8, err error) {
var (
judgementInfo *JudgementInfo
factorMeta FactoryMeta
factor *model.Factor
)
if judgementInfo, err = s.getJudgementInfo(c, mid, ip); err != nil {
return
}
if factorMeta, err = s.getBaseScoreFactor(judgementInfo); err != nil {
return
}
log.Info("getBaseScoreFactor mid(%d) meta(%v)", mid, factorMeta)
if factor, err = s.factor(c, factorMeta.serviceName, factorMeta.eventName, factorMeta.riskLevel); err != nil {
log.Error("s.factor(%s, %s) error(%v)", conf.Conf.Property.Event.ServiceName, conf.Conf.Property.Event.BindMailOnly, 1)
return
}
score = s.calcFactorScore(conf.Conf.Property.Score.BaseInit, factor)
return
}
// ReBuildPortrait reBuild user info.
func (s *Service) ReBuildPortrait(c context.Context, mid int64, reason string) (err error) {
var (
tx *sql.Tx
)
ui, err := s.UserInfo(c, mid, ip.InternalIP())
if err != nil || ui == nil {
log.Error("user portrait not fund, mid(%d, %v), err(%v)", mid, ui, err)
return
}
s.promEventScore.Incr("change")
s.resetScore(c, ui, ui.BaseScore, _score)
if tx, err = s.dao.BeginTran(c); err != nil {
log.Error("s.dao.BeginTran() err(%v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("tx.Rollback() error(%v)", err1)
}
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
}
}()
if err = s.dao.TxUpdateEventScoreReLive(c, tx, ui.Mid, ui.EventScore, ui.Score); err != nil {
log.Error("s.dao.TxUpdateEventScoreReLive(%d, %d, %d), err(%v)", ui.Mid, ui.EventScore, ui.Score, err)
return
}
if err = s.txAddHistory(c, tx, ui, &model.Factor{}, &model.EventMessage{Effect: reason}); err != nil {
log.Error("s.addHistory(%+v), err(%v)", ui, err)
return
}
s.updateInfoCache(c, ui)
s.dao.PubScoreChange(c, mid, &model.ScoreChange{
Mid: mid,
Score: ui.Score,
TS: time.Now().Unix(),
})
return
}
// UpdateUserScore update user score
func (s *Service) UpdateUserScore(c context.Context, mid int64, ip, effect string) (err error) {
var (
tx *sql.Tx
factor = &model.Factor{}
eventMsg = &model.EventMessage{Effect: effect}
preBaseScore int8
)
ui, err := s.UserInfo(c, mid, ip)
if err != nil || ui == nil {
log.Error("user portrait not found, mid(%d, %v), err(%v)", mid, ui, err)
return
}
preBaseScore = ui.BaseScore
if ui.BaseScore, err = s.getBaseScore(c, mid, ip); err != nil {
log.Error("s.calcBaseScore(%d, %s) error(%v)", mid, ip, err)
return
}
s.promBaseScore.Incr("change")
if ui.BaseScore < preBaseScore {
s.promBaseScore.Incr("decrease")
}
s.resetScore(c, ui, ui.BaseScore, ui.EventScore)
if tx, err = s.dao.BeginTran(c); err != nil {
log.Error("s.dao.BeginTran() err(%v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("tx.Rollback() error(%v)", err1)
}
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
}
}()
if err = s.dao.TxUpdateBaseScore(c, tx, ui); err != nil {
log.Error("s.dao.UpdateBaseScore(%v), err(%v)", ui, err)
return
}
if err = s.txAddHistory(c, tx, ui, factor, eventMsg); err != nil {
log.Error("s.addHistory(%v, %v, %v) error(%v)", ui, factor, eventMsg, err)
return
}
s.updateInfoCache(c, ui)
s.dao.PubScoreChange(c, mid, &model.ScoreChange{
Mid: mid,
Score: ui.Score,
TS: time.Now().Unix(),
})
return
}
// RefreshBaseScore refresh base score.
func (s *Service) RefreshBaseScore(c context.Context, arg *spy.ArgReset) (err error) {
var (
tx *sql.Tx
mid = arg.Mid
ip = "ip"
eventMsg = &model.EventMessage{Effect: "手动更新基础分值"}
preBaseScore int8
)
ui, err := s.UserInfo(c, mid, "ip")
if err != nil || ui == nil {
log.Error("user portrait not found, mid(%d, %v), err(%v)", mid, ui, err)
return
}
preBaseScore = ui.BaseScore
if ui.BaseScore, err = s.getBaseScore(c, mid, ip); err != nil {
log.Error("s.calcBaseScore(%d, %s) error(%v)", mid, ip, err)
return
}
s.promBaseScore.Incr("change")
if ui.BaseScore < preBaseScore {
s.promBaseScore.Incr("decrease")
}
s.resetScore(c, ui, ui.BaseScore, ui.EventScore)
if tx, err = s.dao.BeginTran(c); err != nil {
log.Error("s.dao.BeginTran() err(%v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("tx.Rollback() error(%v)", err1)
}
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
}
}()
if err = s.dao.TxUpdateBaseScore(c, tx, ui); err != nil {
log.Error("s.dao.UpdateBaseScore(%v), err(%v)", ui, err)
return
}
if err = s.txAddHistory(c, tx, ui, &model.Factor{}, eventMsg); err != nil {
log.Error("s.addHistory(%v, %v) error(%v)", ui, eventMsg, err)
return
}
s.updateInfoCache(c, ui)
s.dao.PubScoreChange(c, mid, &model.ScoreChange{
Mid: mid,
Score: ui.Score,
TS: time.Now().Unix(),
})
return
}
//UpdateBaseScore update base score.
func (s *Service) UpdateBaseScore(c context.Context, arg *spy.ArgReset) (err error) {
var (
tx *sql.Tx
event *model.Event
eventMsg = &model.EventMessage{}
)
ui, err := s.UserInfo(c, arg.Mid, "ip")
if err != nil || ui == nil {
log.Error("user portrait not fund, mid(%d, %v), err(%v)", arg.Mid, ui, err)
return
}
s.resetScore(c, ui, _score, ui.EventScore)
eventMsg.Effect = fmt.Sprintf("人工恢复基础得分(%s)", arg.Operator)
if tx, err = s.dao.BeginTran(c); err != nil {
log.Error("s.dao.BeginTran() err(%v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("tx.Rollback() error(%v)", err1)
}
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
}
}()
if err = s.dao.TxUpdateBaseScore(c, tx, ui); err != nil {
log.Error("s.dao.UpdateBaseScore(%v), err(%v)", ui, err)
return
}
if event, err = s.dao.Event(c, RestoreBaseScoreEvent); err != nil {
log.Error("s.dao.Event(%s), err(%v)", RestoreBaseScoreEvent, err)
return
}
if err = s.txAddHistory(c, tx, ui, &model.Factor{EventID: event.ID}, eventMsg); err != nil {
log.Error("s.addHistory(%v), err(%v)", ui, err)
return
}
s.dao.DelInfoCache(c, arg.Mid)
s.dao.PubScoreChange(c, arg.Mid, &model.ScoreChange{
Mid: arg.Mid,
Score: ui.Score,
TS: time.Now().Unix(),
})
return
}
//UpdateEventScore update event score.
func (s *Service) UpdateEventScore(c context.Context, arg *spy.ArgReset) (err error) {
var (
tx *sql.Tx
eventMsg = &model.EventMessage{}
)
ui, err := s.UserInfo(c, arg.Mid, "ip")
if err != nil || ui == nil {
log.Error("user portrait not fund, mid(%d, %v), err(%v)", arg.Mid, ui, err)
return
}
s.resetScore(c, ui, ui.BaseScore, _score)
eventMsg.Effect = fmt.Sprintf("人工恢复行为得分(%s)", arg.Operator)
if tx, err = s.dao.BeginTran(c); err != nil {
log.Error("s.dao.BeginTran() err(%v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("tx.Rollback() error(%v)", err1)
}
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
}
}()
if err = s.dao.TxUpdateEventScore(c, tx, ui.Mid, ui.EventScore, ui.Score); err != nil {
log.Error("s.dao.UpdateEventScore(%v), err(%v)", ui, err)
return
}
if err = s.txAddHistory(c, tx, ui, &model.Factor{}, eventMsg); err != nil {
log.Error("s.addHistory(%v), err(%v)", ui, err)
return
}
s.dao.DelInfoCache(c, arg.Mid)
s.dao.PubScoreChange(c, arg.Mid, &model.ScoreChange{
Mid: arg.Mid,
Score: ui.Score,
TS: time.Now().Unix(),
})
return
}
func (s *Service) txAddHistory(c context.Context, tx *sql.Tx, ui *model.UserInfo, factor *model.Factor, eventMsg *model.EventMessage) (err error) {
// append event history
var (
ueh = &model.UserEventHistory{
Mid: ui.Mid,
EventID: factor.EventID,
Score: ui.Score,
BaseScore: ui.BaseScore,
EventScore: ui.EventScore,
Reason: eventMsg.Effect,
FactorVal: factor.FactorVal,
}
remarkBytes []byte
)
if remarkBytes, err = json.Marshal(eventMsg); err != nil {
log.Error("json.Marshal(%v) error(%v)", eventMsg, err)
ueh.Remark = "{}"
} else {
ueh.Remark = string(remarkBytes)
}
if err = s.dao.TxAddEventHistory(c, tx, ueh); err != nil {
log.Error("s.dao.AddEventHistory(%v) error(%v)", ueh, err)
return
}
return
}
func (s *Service) resetScore(c context.Context, ui *model.UserInfo, baseScore, eventScore int8) (err error) {
ui.BaseScore = baseScore
ui.EventScore = eventScore
ui.Score = int8(int(ui.EventScore) * int(ui.BaseScore) / _score)
return
}
func (s *Service) updateInfoCache(c context.Context, ui *model.UserInfo) (err error) {
s.mission(func() {
if err = s.dao.SetUserInfoCache(context.TODO(), ui); err != nil {
log.Error("s.dao.SetInfoCache(%v) error(%v)", ui, err)
}
})
return
}
//ClearReliveTimes clear times.
func (s *Service) ClearReliveTimes(c context.Context, arg *spy.ArgReset) (err error) {
var (
tx *sql.Tx
eventMsg = &model.EventMessage{}
)
ui, err := s.UserInfo(c, arg.Mid, "ip")
if err != nil || ui == nil {
log.Error("user portrait not fund, mid(%d, %v), err(%v)", arg.Mid, ui, err)
return
}
ui.ReliveTimes = 0
eventMsg.Effect = fmt.Sprintf("清除封号记次(%s)", arg.Operator)
if tx, err = s.dao.BeginTran(c); err != nil {
log.Error("s.dao.BeginTran() err(%v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("tx.Rollback() error(%v)", err1)
}
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
}
}()
if err = s.dao.TxClearReliveTimes(c, tx, ui); err != nil {
log.Error("s.dao.ClearReliveTimes(%v), err(%v)", ui, err)
return
}
if err = s.txAddHistory(c, tx, ui, &model.Factor{}, eventMsg); err != nil {
log.Error("s.addHistory(%v), err(%v)", ui, err)
return
}
s.dao.DelInfoCache(c, arg.Mid)
return
}
// TelRiskLevel tel risk level.
func (s *Service) TelRiskLevel(c context.Context, mid int64, ip string) (riskLevel int8, err error) {
var (
tel *model.TelInfo
level int8
)
riskLevel = dao.TelRiskLevelUnknown
if tel, err = s.dao.TelInfo(c, mid); err != nil {
log.Error("s.dao.TelInfo error(%v)", err)
return
}
if len(tel.Tel) == 0 {
log.Warn("mid(%d) no tel info", mid)
return
}
// white tel
if telnum, theErr := strconv.ParseInt(tel.Tel, 10, 64); theErr == nil {
for _, whiteTel := range s.c.Property.White.Tels {
if telnum >= whiteTel.From && telnum <= whiteTel.To {
log.Info("spy hit tel white from [%d] to [%d]", whiteTel.From, whiteTel.To)
riskLevel = dao.TelRiskLevelLow
return
}
}
} else {
log.Error("+v", errors.WithStack(theErr))
}
args := url.Values{}
args.Set("accountType", fmt.Sprintf("%d", model.AccountType))
args.Set("uid", fmt.Sprintf("%d", mid))
args.Set("phoneNumber", tel.Tel)
args.Set("registerTime", fmt.Sprintf("%d", tel.JoinTime))
args.Set("registerIp", tel.JoinIP)
if level, err = s.dao.RegisterProtection(c, args, ip); err != nil {
log.Error("s.dao.RegisterProtection error(%v)", err)
return
}
switch level {
case model.Nomal:
riskLevel = dao.TelRiskLevelLow
case model.LevelOne:
riskLevel = dao.TelRiskLevelMedium
case model.LevelTwo:
riskLevel = dao.TelRiskLevelMedium
case model.LevelThree:
riskLevel = dao.TelRiskLevelHigh
case model.LevelFour:
riskLevel = dao.TelRiskLevelHigh
default:
log.Error(" RegisterProtection not found level (%d)", level)
}
return
}

View File

@ -0,0 +1,59 @@
package service
import (
"context"
"go-common/app/service/main/spy/model"
)
// StatByID spy stat by id or mid.
func (s *Service) StatByID(c context.Context, mid, id int64) (stat []*model.Statistics, err error) {
if mid != 0 && id != 0 {
stat, err = s.dao.StatListByIDAndMid(c, mid, id)
} else {
if id == 0 {
stat, err = s.dao.StatListByMid(c, mid)
} else {
stat, err = s.dao.StatListByID(c, id)
}
}
if len(stat) == 0 {
return
}
for _, st := range stat {
st.EventName = s.allEventName[st.EventID]
}
return
}
// StatByIDGroupEvent spy stat by id or mid.
func (s *Service) StatByIDGroupEvent(c context.Context, mid, id int64) (res []*model.Statistics, err error) {
var (
stat []*model.Statistics
em = make(map[int64]*model.Statistics)
)
if mid != 0 && id != 0 {
stat, err = s.dao.StatListByIDAndMid(c, mid, id)
} else {
if id == 0 {
stat, err = s.dao.StatListByMid(c, mid)
} else {
stat, err = s.dao.StatListByID(c, id)
}
}
if len(stat) == 0 {
return
}
for _, st := range stat {
item, ok := em[st.EventID]
if !ok {
item = &model.Statistics{EventID: st.EventID, EventName: st.EventName}
}
item.Quantity += st.Quantity
em[st.EventID] = item
}
for _, val := range em {
res = append(res, val)
}
return
}