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,111 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"bfs_test.go",
"dao_test.go",
"face_history_test.go",
"member_test.go",
"merak_test.go",
"message_test.go",
"monitor_test.go",
"official_test.go",
"passport_test.go",
"realname_test.go",
"redis_test.go",
"review_test.go",
"search_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/member/conf:go_default_library",
"//app/admin/main/member/model:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/github.com/tsuna/gohbase/hrpc:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"bfs.go",
"dao.go",
"face_history.go",
"member.go",
"merak.go",
"message.go",
"monitor.go",
"official.go",
"passport.go",
"realname.go",
"realname_old.go",
"redis.go",
"review.go",
"search.go",
],
importpath = "go-common/app/admin/main/member/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/member/conf:go_default_library",
"//app/admin/main/member/dao/block:go_default_library",
"//app/admin/main/member/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/elastic:go_default_library",
"//library/database/hbase.v2:go_default_library",
"//library/database/orm: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/net/ip:go_default_library",
"//library/net/metadata:go_default_library",
"//library/queue/databus:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/time:go_default_library",
"//library/xstr:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/tsuna/gohbase/hrpc:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/admin/main/member/dao/block:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,120 @@
package dao
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"hash"
"io/ioutil"
"net/http"
"strconv"
"time"
"go-common/app/admin/main/member/conf"
"go-common/library/ecode"
"github.com/pkg/errors"
)
// UploadImage upload bfs.
func (d *Dao) UploadImage(c context.Context, fileType string, bs []byte, bfsConf *conf.BFS) (location string, err error) {
url := bfsConf.URL + bfsConf.Bucket + "/"
req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bs))
if err != nil {
err = errors.Wrap(err, " UploadImage http.NewRequest() failed")
return
}
expire := time.Now().Unix()
authorization := authorize(bfsConf.Key, bfsConf.Secret, "PUT", bfsConf.Bucket, "", expire)
req.Header.Set("Host", url)
req.Header.Add("Date", fmt.Sprint(expire))
req.Header.Add("Authorization", authorization)
req.Header.Add("Content-Type", fileType)
// timeout
ctx, cancel := context.WithTimeout(c, time.Duration(bfsConf.Timeout))
req = req.WithContext(ctx)
defer cancel()
resp, err := d.bfsclient.Do(req)
if err != nil {
err = errors.Wrapf(ecode.BfsUploadServiceUnavailable, "d.bfsclient.Do error(%v) | url(%s)", err, url)
return
}
if resp.StatusCode != http.StatusOK {
err = errors.Errorf("UploadImage failed,http code:%d", resp.StatusCode)
return
}
header := resp.Header
code := header.Get("Code")
if code != strconv.Itoa(http.StatusOK) {
err = errors.Wrap(ecode.String(code), "UploadImage failed")
return
}
location = header.Get("Location")
return
}
// DelImage del bfs image.
func (d *Dao) DelImage(c context.Context, fileName string, bfsConf *conf.BFS) (err error) {
url := bfsConf.URL + bfsConf.Bucket + "/" + fileName
req, err := http.NewRequest("DELETE", url, nil)
if err != nil {
err = errors.Wrap(err, "DelImage http.NewRequest() failed")
return
}
expire := time.Now().Unix()
authorization := authorize(bfsConf.Key, bfsConf.Secret, "DELETE", bfsConf.Bucket, fileName, expire)
req.Header.Set("Host", url)
req.Header.Add("Date", fmt.Sprint(expire))
req.Header.Add("Authorization", authorization)
// timeout
ctx, cancel := context.WithTimeout(c, time.Duration(bfsConf.Timeout))
req = req.WithContext(ctx)
defer cancel()
resp, err := d.bfsclient.Do(req)
if err != nil {
err = errors.Wrapf(ecode.BfsUploadServiceUnavailable, "d.bfsclient.Do error(%v) | url(%s)", err, url)
return
}
if resp.StatusCode != http.StatusOK {
err = errors.Errorf("DelImage failed,http code:%d", resp.StatusCode)
return
}
header := resp.Header
code := header.Get("Code")
if code != strconv.Itoa(http.StatusOK) {
err = errors.Errorf("DelImage failed,res code:%s", code)
return
}
return
}
// authorize returns authorization for upload file to bfs
func authorize(key, secret, method, bucket, fileName string, expire int64) (authorization string) {
var (
content string
mac hash.Hash
signature string
)
content = fmt.Sprintf("%s\n%s\n%s\n%d\n", method, bucket, fileName, expire)
mac = hmac.New(sha1.New, []byte(secret))
mac.Write([]byte(content))
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
authorization = fmt.Sprintf("%s:%s:%d", key, signature, expire)
return
}
//Image image.
func (d *Dao) Image(url string) ([]byte, error) {
resp, err := d.bfsclient.Get(url)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, errors.Errorf("Image url(%s) resp.StatusCode code(%v)", url, resp.StatusCode)
}
defer resp.Body.Close()
return ioutil.ReadAll(resp.Body)
}

View File

@@ -0,0 +1,18 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestDao_DelImage(t *testing.T) {
Convey("DelImage", t, func() {
Convey("when not exist, err should not nil", func() {
// FIXME : 该UT不可重入
err := d.DelImage(context.Background(), "130d0e4aa718fcab4abd3ad756ef57017e42bcf4.png", d.c.FaceBFS)
So(err, ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,63 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"http_test.go",
"mc_test.go",
"mysql_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/member/conf:go_default_library",
"//app/admin/main/member/model/block:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/sql:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"http.go",
"mc.go",
"mysql.go",
],
importpath = "go-common/app/admin/main/member/dao/block",
tags = ["automanaged"],
deps = [
"//app/admin/main/member/conf:go_default_library",
"//app/admin/main/member/model/block:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/net/http/blademaster: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,53 @@
package block
import (
"context"
"go-common/app/admin/main/member/conf"
"go-common/library/cache/memcache"
xsql "go-common/library/database/sql"
bm "go-common/library/net/http/blademaster"
"github.com/pkg/errors"
)
// Dao .
type Dao struct {
conf *conf.Config
mc *memcache.Pool
db *xsql.DB
httpClient *bm.Client
}
// New init mysql db
func New(conf *conf.Config, client *bm.Client, mc *memcache.Pool, db *xsql.DB) (dao *Dao) {
dao = &Dao{
conf: conf,
mc: mc,
db: db,
httpClient: client,
}
return
}
// BeginTX .
func (d *Dao) BeginTX(c context.Context) (tx *xsql.Tx, err error) {
if tx, err = d.db.Begin(c); err != nil {
err = errors.WithStack(err)
}
return
}
// Close close the resource.
func (d *Dao) Close() {
d.mc.Close()
d.db.Close()
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.db.Ping(c); err != nil {
return
}
return
}

View File

@@ -0,0 +1,39 @@
package block
import (
"flag"
"os"
"testing"
"go-common/app/admin/main/member/conf"
"go-common/library/cache/memcache"
xsql "go-common/library/database/sql"
bm "go-common/library/net/http/blademaster"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.account.member-admin")
flag.Set("conf_token", "c18eac2285e4e4a75a8672139c30d464")
flag.Set("tree_id", "2135")
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/member-admin-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
hc := bm.NewClient(conf.Conf.HTTPClient.Read)
d = New(conf.Conf, hc, memcache.NewPool(conf.Conf.BlockMemcache), xsql.NewMySQL(conf.Conf.BlockMySQL))
os.Exit(m.Run())
}

View File

@@ -0,0 +1,203 @@
package block
import (
"context"
"fmt"
"net/url"
"strings"
"time"
model "go-common/app/admin/main/member/model/block"
"go-common/library/ecode"
"github.com/pkg/errors"
)
// BlackhouseBlock .
func (d *Dao) BlackhouseBlock(c context.Context, p *model.ParamBatchBlock) (err error) {
midStrs := make([]string, len(p.MIDs))
for i, mid := range p.MIDs {
midStrs[i] = fmt.Sprintf("%d", mid)
}
params := url.Values{}
params.Set("mids", strings.Join(midStrs, ","))
params.Set("oper_id", fmt.Sprintf("%d", p.AdminID))
params.Set("operator_name", p.AdminName)
params.Set("blocked_days", fmt.Sprintf("%d", p.Duration))
switch p.Action {
case model.BlockActionForever:
params.Set("blocked_forever", "1")
params.Set("punish_type", "3")
default:
params.Set("blocked_forever", "0")
params.Set("punish_type", "2")
}
params.Set("blocked_remark", p.Comment)
params.Set("origin_type", fmt.Sprintf("%d", p.Area))
params.Set("punish_time", fmt.Sprintf("%d", time.Now().Unix()))
params.Set("reason_type", fmt.Sprintf("%d", parseReasonType(p.Reason)))
var res struct {
Code int `json:"code"`
}
if err = d.httpClient.Post(c, d.conf.BlockProperty.BlackHouseURL, "", params, &res); err != nil {
err = errors.WithStack(err)
return
}
if res.Code != 0 {
err = errors.WithStack(ecode.Int(res.Code))
return
}
return
}
func parseReasonType(msg string) (t int) {
switch msg {
case "刷屏":
t = 1
case "抢楼":
t = 2
case "发布色情低俗信息":
t = 3
case "发布赌博诈骗信息":
t = 4
case "发布违禁相关信息", "发布违禁信息":
t = 5
case "发布垃圾广告信息":
t = 6
case "发布人身攻击言论":
t = 7
case "发布侵犯他人隐私信息":
t = 8
case "发布引战言论":
t = 9
case "发布剧透信息":
t = 10
case "恶意添加无关标签":
t = 11
case "恶意删除他人标签":
t = 12
case "发布色情信息":
t = 13
case "发布低俗信息":
t = 14
case "发布暴力血腥信息":
t = 15
case "涉及恶意投稿行为":
t = 16
case "发布非法网站信息":
t = 17
case "发布传播不实信息":
t = 18
case "发布怂恿教唆信息":
t = 19
case "恶意刷屏":
t = 20
case "账号违规":
t = 21
case "恶意抄袭":
t = 22
case "冒充自制原创":
t = 23
case "发布青少年不良内容":
t = 24
case "破坏网络安全":
t = 25
case "发布虚假误导信息":
t = 26
case "仿冒官方认证账号":
t = 27
case "发布不适宜内容":
t = 28
case "违反运营规则":
t = 29
case "恶意创建话题":
t = 30
case "发布违规抽奖":
t = 31
case "恶意冒充他人":
t = 32
default:
t = 0
}
return
}
// SendSysMsg send sys msg.
func (d *Dao) SendSysMsg(c context.Context, code string, mids []int64, title string, content string, remoteIP string) (err error) {
params := url.Values{}
params.Set("mc", code)
params.Set("title", title)
params.Set("data_type", "4")
params.Set("context", content)
params.Set("mid_list", midsToParam(mids))
var res struct {
Code int `json:"code"`
Data *struct {
Status int8 `json:"status"`
Remark string `json:"remark"`
} `json:"data"`
}
if err = d.httpClient.Post(c, d.conf.BlockProperty.MSGURL, remoteIP, params, &res); err != nil {
err = errors.WithStack(err)
return
}
if res.Code != 0 {
err = errors.WithStack(ecode.Int(res.Code))
return
}
return
}
func midsToParam(mids []int64) (str string) {
strs := make([]string, 0, len(mids))
for _, mid := range mids {
strs = append(strs, fmt.Sprintf("%d", mid))
}
return strings.Join(strs, ",")
}
// TelInfo tel info.
func (d *Dao) TelInfo(c context.Context, mid int64) (tel string, err error) {
params := url.Values{}
params.Set("mid", fmt.Sprintf("%d", mid))
var resp struct {
Code int `json:"code"`
Data struct {
Mid int64 `json:"mid"`
Tel string `json:"tel"`
JoinIP string `json:"join_ip"`
JoinTime int64 `json:"join_time"`
} `json:"data"`
}
if err = d.httpClient.Get(c, d.conf.BlockProperty.TelURL, "", params, &resp); err != nil {
err = errors.Wrapf(err, "telinfo : %d", mid)
return
}
if resp.Code != 0 {
err = errors.Errorf("telinfo url(%s) res(%+v) err(%+v)", d.conf.BlockProperty.TelURL+"?"+params.Encode(), resp, ecode.Int(resp.Code))
return
}
tel = resp.Data.Tel
return
}
// MailInfo .
func (d *Dao) MailInfo(c context.Context, mid int64) (mail string, err error) {
params := url.Values{}
params.Set("mid", fmt.Sprintf("%d", mid))
var resp struct {
Code int `json:"code"`
Data string `json:"data"`
}
if err = d.httpClient.Get(c, d.conf.BlockProperty.MailURL, "", params, &resp); err != nil {
err = errors.Wrapf(err, "mailinfo : %d", mid)
return
}
if resp.Code != 0 {
err = errors.Errorf("mailinfo url(%s) res(%+v) err(%+v)", d.conf.BlockProperty.MailURL+"?"+params.Encode(), resp, ecode.Int(resp.Code))
return
}
mail = resp.Data
return
}

View File

@@ -0,0 +1,103 @@
package block
import (
"context"
model "go-common/app/admin/main/member/model/block"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestBlockBlackhouseBlock(t *testing.T) {
convey.Convey("BlackhouseBlock", t, func(ctx convey.C) {
var (
c = context.Background()
p = &model.ParamBatchBlock{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.BlackhouseBlock(c, p)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
func TestBlockparseReasonType(t *testing.T) {
convey.Convey("parseReasonType", t, func(ctx convey.C) {
var (
msg = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
no := parseReasonType(msg)
ctx.Convey("Then no should not be nil.", func(ctx convey.C) {
ctx.So(no, convey.ShouldNotBeNil)
})
})
})
}
func TestBlockSendSysMsg(t *testing.T) {
convey.Convey("SendSysMsg", t, func(ctx convey.C) {
var (
c = context.Background()
code = ""
mids = []int64{}
title = ""
content = ""
remoteIP = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.SendSysMsg(c, code, mids, title, content, remoteIP)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
func TestBlockmidsToParam(t *testing.T) {
convey.Convey("midsToParam", t, func(ctx convey.C) {
var (
mids = []int64{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
str := midsToParam(mids)
ctx.Convey("Then str should not be nil.", func(ctx convey.C) {
ctx.So(str, convey.ShouldNotBeNil)
})
})
})
}
func TestBlockTelInfo(t *testing.T) {
convey.Convey("TelInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
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.ShouldNotBeNil)
ctx.So(tel, convey.ShouldEqual, "")
})
})
})
}
func TestBlockMailInfo(t *testing.T) {
convey.Convey("MailInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
mail, err := d.MailInfo(c, mid)
ctx.Convey("Then err should be nil.mail should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(mail, convey.ShouldEqual, "")
})
})
})
}

View File

@@ -0,0 +1,49 @@
package block
import (
"context"
"fmt"
"go-common/library/cache/memcache"
"github.com/pkg/errors"
)
func userKey(mid int64) (key string) {
key = fmt.Sprintf("u_%d", mid)
return
}
func userDetailKey(mid int64) (key string) {
key = fmt.Sprintf("ud_%d", mid)
return
}
// DeleteUserCache .
func (d *Dao) DeleteUserCache(c context.Context, mid int64) (err error) {
var (
key = userKey(mid)
conn = d.mc.Get(c)
)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
err = errors.Wrapf(err, "key : %s", key)
return
}
return
}
// DeleteUserDetailCache delete user detail cache
func (d *Dao) DeleteUserDetailCache(c context.Context, mid int64) (err error) {
var (
key = userDetailKey(mid)
conn = d.mc.Get(c)
)
defer conn.Close()
err = conn.Delete(key)
return
}

View File

@@ -0,0 +1,37 @@
package block
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestBlockuserKey(t *testing.T) {
convey.Convey("userKey", t, func(ctx convey.C) {
var (
mid = int64(46333)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
key := userKey(mid)
ctx.Convey("Then key should not be nil.", func(ctx convey.C) {
ctx.So(key, convey.ShouldEqual, "u_46333")
})
})
})
}
func TestBlockDeleteUserCache(t *testing.T) {
convey.Convey("DeleteUserCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DeleteUserCache(c, mid)
ctx.Convey("test DeleteUserCache", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,180 @@
package block
import (
"context"
"fmt"
"strings"
model "go-common/app/admin/main/member/model/block"
xsql "go-common/library/database/sql"
"github.com/pkg/errors"
)
const (
_user = `SELECT id,mid,status,ctime,mtime FROM block_user WHERE mid=? LIMIT 1`
_users = `SELECT id,mid,status,ctime,mtime FROM block_user WHERE mid IN (%s)`
_upsertUser = `INSERT INTO block_user (mid,status) VALUES (?,?) ON DUPLICATE KEY UPDATE status=?`
_userDetails = `SELECT id,mid,block_count,ctime,mtime FROM block_user_detail WHERE mid IN (%s)`
_addAddBlockCount = `INSERT INTO block_user_detail (mid,block_count) VALUES (?,1) ON DUPLICATE KEY UPDATE block_count=block_count+1`
_history = `SELECT id,mid,admin_id,admin_name,source,area,reason,comment,action,start_time,
duration,notify,ctime,mtime FROM block_history_%d WHERE mid=? ORDER BY mtime %s LIMIT ?,? `
_historyCount = `SELECT count(*) FROM block_history_%d WHERE mid=? LIMIT 1`
_insertHistory = `INSERT INTO block_history_%d (mid,admin_id,admin_name,source,area,reason,comment,action,start_time,duration,notify) VALUES (?,?,?,?,?,?,?,?,?,?,?)`
)
func historyIdx(mid int64) int64 {
return mid % 10
}
// User .
func (d *Dao) User(c context.Context, mid int64) (user *model.DBUser, err error) {
user = &model.DBUser{}
row := d.db.QueryRow(c, _user, mid)
if err = row.Scan(&user.ID, &user.MID, &user.Status, &user.CTime, &user.MTime); err != nil {
err = nil
user = nil
return
}
return
}
// Users .
func (d *Dao) Users(c context.Context, mids []int64) (users []*model.DBUser, err error) {
if len(mids) == 0 {
return
}
var (
sql = fmt.Sprintf(_users, strings.Join(intsToStrs(mids), ","))
rows *xsql.Rows
)
if rows, err = d.db.Query(c, sql); err != nil {
err = errors.WithStack(err)
return
}
defer rows.Close()
for rows.Next() {
user := &model.DBUser{}
if err = rows.Scan(&user.ID, &user.MID, &user.Status, &user.CTime, &user.MTime); err != nil {
err = errors.WithStack(err)
return
}
users = append(users, user)
}
if err = rows.Err(); err != nil {
err = errors.WithStack(err)
}
return
}
// TxUpdateUser .
func (d *Dao) TxUpdateUser(c context.Context, tx *xsql.Tx, mid int64, status model.BlockStatus) (err error) {
if _, err = tx.Exec(_upsertUser, mid, status, status); err != nil {
err = errors.WithStack(err)
return
}
return
}
// UserDetails .
func (d *Dao) UserDetails(c context.Context, mids []int64) (users []*model.DBUserDetail, err error) {
if len(mids) == 0 {
return
}
var (
sql = fmt.Sprintf(_userDetails, strings.Join(intsToStrs(mids), ","))
rows *xsql.Rows
)
if rows, err = d.db.Query(c, sql); err != nil {
err = errors.WithStack(err)
return
}
defer rows.Close()
for rows.Next() {
user := &model.DBUserDetail{}
if err = rows.Scan(&user.ID, &user.MID, &user.BlockCount, &user.CTime, &user.MTime); err != nil {
err = errors.WithStack(err)
return
}
users = append(users, user)
}
if err = rows.Err(); err != nil {
err = errors.WithStack(err)
}
return
}
// UpdateAddBlockCount .
func (d *Dao) UpdateAddBlockCount(c context.Context, mid int64) (err error) {
if _, err = d.db.Exec(c, _addAddBlockCount, mid); err != nil {
err = errors.WithStack(err)
return
}
return
}
// History 获得mid历史封禁记录
func (d *Dao) History(c context.Context, mid int64, start, limit int, desc bool) (history []*model.DBHistory, err error) {
var (
rows *xsql.Rows
)
order := "ASC"
if desc {
order = "DESC"
}
sql := fmt.Sprintf(_history, historyIdx(mid), order)
if rows, err = d.db.Query(c, sql, mid, start, limit); err != nil {
err = errors.WithStack(err)
return
}
defer rows.Close()
for rows.Next() {
h := &model.DBHistory{}
if err = rows.Scan(&h.ID, &h.MID, &h.AdminID, &h.AdminName, &h.Source, &h.Area, &h.Reason, &h.Comment, &h.Action, &h.StartTime, &h.Duration, &h.Notify, &h.CTime, &h.MTime); err != nil {
err = errors.WithStack(err)
return
}
history = append(history, h)
}
if err = rows.Err(); err != nil {
return
}
return
}
// HistoryCount 获得历史记录总长度
func (d *Dao) HistoryCount(c context.Context, mid int64) (total int, err error) {
var (
row *xsql.Row
sql = fmt.Sprintf(_historyCount, historyIdx(mid))
)
row = d.db.QueryRow(c, sql, mid)
if err = row.Scan(&total); err != nil {
err = errors.WithStack(err)
return
}
return
}
// TxInsertHistory .
func (d *Dao) TxInsertHistory(c context.Context, tx *xsql.Tx, h *model.DBHistory) (err error) {
var (
sql = fmt.Sprintf(_insertHistory, historyIdx(h.MID))
)
if _, err = tx.Exec(sql, h.MID, h.AdminID, h.AdminName, h.Source, h.Area, h.Reason, h.Comment, h.Action, h.StartTime, h.Duration, h.Notify); err != nil {
err = errors.WithStack(err)
return
}
return
}
func intsToStrs(ints []int64) (strs []string) {
for _, i := range ints {
strs = append(strs, fmt.Sprintf("%d", i))
}
return
}

View File

@@ -0,0 +1,174 @@
package block
import (
"context"
model "go-common/app/admin/main/member/model/block"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestBlockhistoryIdx(t *testing.T) {
convey.Convey("historyIdx", t, func(ctx convey.C) {
var (
mid = int64(46333)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := historyIdx(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestBlockUser(t *testing.T) {
convey.Convey("User", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(46333)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
user, err := d.User(c, mid)
ctx.Convey("Then err should be nil.user should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(user, convey.ShouldNotBeNil)
})
})
})
}
func TestBlockUsers(t *testing.T) {
convey.Convey("Users", t, func(ctx convey.C) {
var (
c = context.Background()
mids = []int64{46333}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
users, err := d.Users(c, mids)
ctx.Convey("Then err should be nil.users should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(users, convey.ShouldNotBeNil)
})
})
})
}
func TestBlockTxUpdateUser(t *testing.T) {
convey.Convey("TxUpdateUser", t, func(ctx convey.C) {
var (
c = context.Background()
tx, _ = d.BeginTX(c)
mid = int64(46333)
status model.BlockStatus = model.BlockStatusFalse
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.TxUpdateUser(c, tx, mid, status)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestBlockUserDetails(t *testing.T) {
convey.Convey("UserDetails", t, func(ctx convey.C) {
var (
c = context.Background()
mids = []int64{46333}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
users, err := d.UserDetails(c, mids)
ctx.Convey("Then err should be nil.users should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(users, convey.ShouldNotBeNil)
})
})
})
}
func TestBlockUpdateAddBlockCount(t *testing.T) {
convey.Convey("UpdateAddBlockCount", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(46333)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.UpdateAddBlockCount(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestBlockHistory(t *testing.T) {
convey.Convey("History", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(46333)
start = int(0)
limit = int(10)
desc bool
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
history, err := d.History(c, mid, start, limit, desc)
ctx.Convey("Then err should be nil.history should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(history, convey.ShouldNotBeNil)
})
})
})
}
func TestBlockHistoryCount(t *testing.T) {
convey.Convey("HistoryCount", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(46333)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
total, err := d.HistoryCount(c, mid)
ctx.Convey("Then err should be nil.total should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(total, convey.ShouldNotBeNil)
})
})
})
}
func TestBlockTxInsertHistory(t *testing.T) {
convey.Convey("TxInsertHistory", t, func(ctx convey.C) {
var (
c = context.Background()
tx, _ = d.BeginTX(c)
h = &model.DBHistory{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.TxInsertHistory(c, tx, h)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
ctx.Reset(func() {
tx.Commit()
})
})
}
func TestBlockintsToStrs(t *testing.T) {
convey.Convey("intsToStrs", t, func(ctx convey.C) {
var (
ints = []int64{46333}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
strs := intsToStrs(ints)
ctx.Convey("Then strs should not be nil.", func(ctx convey.C) {
ctx.So(strs, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,100 @@
package dao
import (
"context"
xhttp "net/http"
"time"
"go-common/app/admin/main/member/conf"
"go-common/app/admin/main/member/dao/block"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/database/elastic"
"go-common/library/database/orm"
"go-common/library/database/sql"
bm "go-common/library/net/http/blademaster"
"go-common/library/queue/databus"
"go-common/library/database/hbase.v2"
"github.com/jinzhu/gorm"
)
// Dao dao
type Dao struct {
c *conf.Config
// db
member *gorm.DB
memberRead *gorm.DB
account *gorm.DB
block *block.Dao
fhbyophbase *hbase.Client
fhbymidhbase *hbase.Client
httpClient *bm.Client
passportClient *bm.Client
bfsclient *xhttp.Client
upUnameURL string
queryByMidsURL string
msgURL string
expMsgDatabus *databus.Databus
es *elastic.Elastic
redis *redis.Pool
memcache *memcache.Pool
merakURL string
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
member: orm.NewMySQL(c.ORM.Member),
memberRead: orm.NewMySQL(c.ORM.MemberRead),
account: orm.NewMySQL(c.ORM.Account), // account-php 库
fhbyophbase: hbase.NewClient(c.FHByOPHBase),
fhbymidhbase: hbase.NewClient(c.FHByMidHBase),
httpClient: bm.NewClient(c.HTTPClient.Read),
passportClient: bm.NewClient(c.HTTPClient.Passport),
bfsclient: &xhttp.Client{Timeout: time.Duration(c.FacePriBFS.Timeout)},
msgURL: c.Host.Message + _msgURL,
upUnameURL: c.Host.Passport + _updateUname,
queryByMidsURL: c.Host.Passport + _queryByMids,
merakURL: c.Host.Merak + "/",
expMsgDatabus: databus.New(c.ExpMsgDatabus),
es: elastic.NewElastic(c.ES),
redis: redis.NewPool(c.Redis),
memcache: memcache.NewPool(c.Memcache),
}
dao.block = block.New(c, dao.httpClient, memcache.NewPool(c.BlockMemcache), sql.NewMySQL(c.BlockMySQL))
dao.initORM()
return
}
// Close close the resource.
func (d *Dao) Close() {
if d.member != nil {
d.member.Close()
}
if d.redis != nil {
d.redis.Close()
}
}
func (d *Dao) initORM() {
d.member.LogMode(true)
}
// Ping dao ping
func (d *Dao) Ping(ctx context.Context) (err error) {
if err = d.member.DB().PingContext(ctx); err != nil {
return
}
if err = d.pingRedis(ctx); err != nil {
return
}
return
}
// BlockImpl is
func (d *Dao) BlockImpl() *block.Dao {
return d.block
}

View File

@@ -0,0 +1,43 @@
package dao
import (
"flag"
"os"
"strings"
"testing"
"go-common/app/admin/main/member/conf"
"gopkg.in/h2non/gock.v1"
)
var d *Dao
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.account.member-admin")
flag.Set("conf_token", "c18eac2285e4e4a75a8672139c30d464")
flag.Set("tree_id", "2135")
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/member-admin-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
d.httpClient.SetTransport(gock.DefaultTransport)
os.Exit(m.Run())
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}

View File

@@ -0,0 +1,233 @@
package dao
import (
"context"
"fmt"
"io"
"math"
"strconv"
"strings"
"sync"
"go-common/app/admin/main/member/model"
"go-common/library/log"
"go-common/library/sync/errgroup"
xtime "go-common/library/time"
"github.com/tsuna/gohbase/hrpc"
)
var (
tableFaceByMidHistory = "account:user_face"
tableFaceByOPHistory = "account:user_face_admin"
)
// reverse returns its argument string reversed rune-wise left to right.
func reverse(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)
}
func rpad(s string, c string, l int) string {
dt := l - len(s)
if dt <= 0 {
return s
}
return s + strings.Repeat(c, dt)
}
// func lpad(s string, c string, l int) string {
// dt := l - len(s)
// if dt <= 0 {
// return s
// }
// return strings.Repeat(c, dt) + s
// }
func midKey(mid int64, time xtime.Time) string {
suf := rpad(strconv.FormatInt(math.MaxInt64-int64(time), 10), "0", 10)
return fmt.Sprintf("%s%s", rpad(reverse(strconv.FormatInt(mid, 10)), "0", 10), string(suf[len(suf)-10:]))
}
func operatorKey(operator string, time xtime.Time) string {
suf := rpad(strconv.FormatInt(math.MaxInt64-int64(time), 10), "0", 10)
return fmt.Sprintf("%s%s", rpad(operator, "-", 20), string(suf[len(suf)-10:]))
}
func scanTimes(tDuration xtime.Time) int {
times := int(tDuration)/(60*60) + 5
if times > 50 {
times = 50
}
return times
}
// FaceHistoryByMid is.
func (d *Dao) FaceHistoryByMid(ctx context.Context, arg *model.ArgFaceHistory) (model.FaceRecordList, error) {
size := arg.ETime - arg.STime
stimes := scanTimes(size)
chunk := xtime.Time(size / xtime.Time(stimes))
if chunk == 0 {
chunk = size
}
rendKey, rstartKey := midKey(arg.Mid, arg.STime), midKey(arg.Mid, arg.ETime)
eg := errgroup.Group{}
lock := sync.RWMutex{}
records := make(model.FaceRecordList, 0)
for i := 0; i < stimes; i++ {
times := i + 1
stime := arg.STime + (chunk * xtime.Time(i))
etime := arg.STime + (chunk * xtime.Time(i+1))
eg.Go(func() error {
endKey, startKey := midKey(arg.Mid, stime), midKey(arg.Mid, etime)
log.Info("FaceHistoryByMid: range: start: %s end: %s with times: %d scaning key: start: %s end: %s",
rstartKey, rendKey, times, startKey, endKey)
scanner, err := d.fhbymidhbase.ScanRangeStr(ctx, tableFaceByMidHistory, startKey, endKey)
if err != nil {
log.Error("hbase.ScanRangeStr(%s,%+v) error(%v)", tableFaceByMidHistory, arg, err)
return err
}
for {
r, err := scanner.Next()
if err != nil {
if err != io.EOF {
return err
}
break
}
lock.Lock()
records = append(records, toMidFaceRecord(r))
lock.Unlock()
}
return nil
})
if etime >= arg.ETime {
break
}
}
if err := eg.Wait(); err != nil {
return nil, err
}
return records, nil
}
// FaceHistoryByOP is.
func (d *Dao) FaceHistoryByOP(ctx context.Context, arg *model.ArgFaceHistory) (model.FaceRecordList, error) {
size := arg.ETime - arg.STime
stimes := scanTimes(size)
chunk := xtime.Time(size / xtime.Time(stimes))
if chunk == 0 {
chunk = size
}
rendKey, rstartKey := operatorKey(arg.Operator, arg.STime), operatorKey(arg.Operator, arg.ETime)
eg := errgroup.Group{}
lock := sync.RWMutex{}
records := make(model.FaceRecordList, 0)
for i := 0; i < stimes; i++ {
times := i + 1
stime := arg.STime + (chunk * xtime.Time(i))
etime := arg.STime + (chunk * xtime.Time(i+1))
eg.Go(func() error {
endKey, startKey := operatorKey(arg.Operator, stime), operatorKey(arg.Operator, etime)
log.Info("FaceHistoryByOP: range: start: %s end: %s with times: %d scaning key: start: %s end: %s",
rstartKey, rendKey, times, startKey, endKey)
scanner, err := d.fhbyophbase.ScanRangeStr(ctx, tableFaceByOPHistory, startKey, endKey)
if err != nil {
log.Error("hbase.ScanRangeStr(%s,%+v) error(%v)", tableFaceByOPHistory, arg, err)
return err
}
for {
r, err := scanner.Next()
if err != nil {
if err != io.EOF {
return err
}
break
}
lock.Lock()
records = append(records, toOPFaceRecord(r))
lock.Unlock()
}
return nil
})
if etime >= arg.ETime {
break
}
}
if err := eg.Wait(); err != nil {
return nil, err
}
return records, nil
}
func toOPFaceRecord(res *hrpc.Result) *model.FaceRecord {
l := &model.FaceRecord{}
for _, c := range res.Cells {
key := string(c.Row)
qf := string(c.Qualifier)
v := string(c.Value)
log.Info("Retrieving op face record history: key(%s) qualifier(%s) value(%s)", key, qf, v)
// fill fields
switch qf {
case "id":
l.ID, _ = strconv.ParseInt(v, 10, 64)
case "mid":
l.Mid, _ = strconv.ParseInt(v, 10, 64)
case "sta":
l.Status = model.ParseStatus(v)
case "op":
l.Operator = v
case "old":
l.OldFace = v
case "new":
l.NewFace = v
case "apply":
l.ApplyTime = model.ParseApplyTime(v)
case "mtm":
l.ModifyTime, _ = model.ParseLogTime(v)
}
}
return l
}
func toMidFaceRecord(res *hrpc.Result) *model.FaceRecord {
l := &model.FaceRecord{}
for _, c := range res.Cells {
key := string(c.Row)
qf := string(c.Qualifier)
v := string(c.Value)
log.Info("Retrieving mid face record history: key(%s) qualifier(%s) value(%s)", key, qf, v)
// fill fields
switch qf {
// case "id":
// l.ID, _ = strconv.ParseInt(v, 10, 64)
case "mid":
l.Mid, _ = strconv.ParseInt(v, 10, 64)
case "s":
l.Status = model.ParseStatus(v)
case "op":
l.Operator = v
case "of":
l.OldFace = v
case "nf":
l.NewFace = v
case "at":
l.ApplyTime = model.ParseApplyTime(v)
case "mt":
l.ModifyTime, _ = model.ParseLogTime(v)
}
}
return l
}

View File

@@ -0,0 +1,143 @@
package dao
import (
xtime "go-common/library/time"
"testing"
"github.com/smartystreets/goconvey/convey"
"github.com/tsuna/gohbase/hrpc"
)
func TestDaoreverse(t *testing.T) {
convey.Convey("reverse", t, func(ctx convey.C) {
var (
s = "123"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := reverse(s)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldEqual, "321")
})
})
})
}
func TestDaorpad(t *testing.T) {
convey.Convey("rpad", t, func(ctx convey.C) {
var (
s = "123"
c = "a"
l = int(4)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := rpad(s, c, l)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldEqual, "123a")
})
})
})
}
func TestDaomidKey(t *testing.T) {
convey.Convey("midKey", t, func(ctx convey.C) {
var (
mid = int64(1)
time xtime.Time
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := midKey(mid, time)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaooperatorKey(t *testing.T) {
convey.Convey("operatorKey", t, func(ctx convey.C) {
var (
operator = "admin"
time xtime.Time
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := operatorKey(operator, time)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoscanTimes(t *testing.T) {
convey.Convey("scanTimes", t, func(ctx convey.C) {
var (
tDuration xtime.Time
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := scanTimes(tDuration)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoFaceHistoryByMid(t *testing.T) {
convey.Convey("FaceHistoryByMid", t, func(ctx convey.C) {
// var (
// c = context.Background()
// arg = &model.ArgFaceHistory{}
// )
ctx.Convey("When everything goes positive", func(ctx convey.C) {
// p1, err := d.FaceHistoryByMid(c, arg)
// 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 TestDaoFaceHistoryByOP(t *testing.T) {
convey.Convey("FaceHistoryByOP", t, func(ctx convey.C) {
// var (
// c = context.Background()
// arg = &model.ArgFaceHistory{}
// )
ctx.Convey("When everything goes positive", func(ctx convey.C) {
// p1, err := d.FaceHistoryByOP(c, arg)
// 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 TestDaotoOPFaceRecord(t *testing.T) {
convey.Convey("toOPFaceRecord", t, func(ctx convey.C) {
var (
res = &hrpc.Result{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := toOPFaceRecord(res)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaotoMidFaceRecord(t *testing.T) {
convey.Convey("toMidFaceRecord", t, func(ctx convey.C) {
var (
res = &hrpc.Result{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := toMidFaceRecord(res)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,147 @@
package dao
import (
"context"
"fmt"
"strconv"
"go-common/app/admin/main/member/model"
"github.com/pkg/errors"
)
var (
_sharding = int64(100)
)
func baseTable(mid int64) string {
return fmt.Sprintf("user_base_%02d", mid%_sharding)
}
func expTable(mid int64) string {
return fmt.Sprintf("user_exp_%02d", mid%_sharding)
}
// Base is.
func (d *Dao) Base(ctx context.Context, mid int64) (*model.Base, error) {
b := &model.Base{}
if err := d.member.Table(baseTable(mid)).Where("mid=?", mid).Find(b).Error; err != nil {
return nil, err
}
b.RandFaceURL()
return b, nil
}
// Bases is.
func (d *Dao) Bases(ctx context.Context, mids []int64) (map[int64]*model.Base, error) {
bs := make(map[int64]*model.Base, len(mids))
for _, mid := range mids {
b, err := d.Base(ctx, mid)
if err != nil {
continue
}
bs[b.Mid] = b
}
return bs, nil
}
// Exp is.
func (d *Dao) Exp(ctx context.Context, mid int64) (*model.Exp, error) {
e := &model.Exp{}
if err := d.member.Table(expTable(mid)).Where("mid=?", mid).Find(e).Error; err != nil {
return nil, err
}
return e, nil
}
// Moral is.
func (d *Dao) Moral(ctx context.Context, mid int64) (*model.Moral, error) {
m := &model.Moral{
Mid: mid,
Moral: 7000,
}
if err := d.member.Table("user_moral").
Where(&model.Moral{Mid: mid}).
FirstOrCreate(m).Error; err != nil {
return nil, err
}
return m, nil
}
// UpName is.
func (d *Dao) UpName(ctx context.Context, mid int64, name string) error {
ups := map[string]string{
"name": name,
}
if err := d.member.Table(baseTable(mid)).Where("mid=?", mid).Updates(ups).Error; err != nil {
err = errors.Wrap(err, "dao update name")
return err
}
return nil
}
// UpSign is.
func (d *Dao) UpSign(ctx context.Context, mid int64, sign string) error {
ups := map[string]string{
"sign": sign,
}
if err := d.member.Table(baseTable(mid)).Where("mid=?", mid).Updates(ups).Error; err != nil {
err = errors.Wrap(err, "dao update sign")
return err
}
return nil
}
// UpFace is.
func (d *Dao) UpFace(ctx context.Context, mid int64, face string) error {
ups := map[string]string{
"face": face,
}
if err := d.member.Table(baseTable(mid)).Where("mid=?", mid).Updates(ups).Error; err != nil {
err = errors.Wrap(err, "dao update face")
return err
}
return nil
}
// BatchUserAddit is.
func (d *Dao) BatchUserAddit(ctx context.Context, mids []int64) (map[int64]*model.UserAddit, error) {
uas := []*model.UserAddit{}
if err := d.member.Table("user_addit").Where("mid in (?)", mids).Find(&uas).Error; err != nil {
return nil, err
}
uasMap := make(map[int64]*model.UserAddit, len(uas))
for _, ua := range uas {
uasMap[ua.Mid] = ua
}
return uasMap, nil
}
// PubExpMsg is.
func (d *Dao) PubExpMsg(ctx context.Context, msg *model.AddExpMsg) error {
return d.expMsgDatabus.Send(ctx, strconv.FormatInt(msg.Mid, 10), msg)
}
// UserAddit is.
func (d *Dao) UserAddit(ctx context.Context, mid int64) (*model.UserAddit, error) {
addit := &model.UserAddit{}
if err := d.member.Table("user_addit").Where("mid=?", mid).Find(addit).Error; err != nil {
return nil, err
}
return addit, nil
}
// UpAdditRemark update remark.
func (d *Dao) UpAdditRemark(ctx context.Context, mid int64, remark string) error {
addit := &model.UserAddit{
Mid: mid,
}
upRemark := map[string]string{
"remark": remark,
}
if err := d.member.Table("user_addit").Where("mid=?", mid).Assign(upRemark).FirstOrCreate(addit).Error; err != nil {
err = errors.Wrap(err, "dao insert or update addit")
return err
}
return nil
}

View File

@@ -0,0 +1,97 @@
package dao
import (
"context"
"fmt"
"testing"
"time"
"go-common/app/admin/main/member/model"
"github.com/smartystreets/goconvey/convey"
)
func TestBase(t *testing.T) {
convey.Convey("Base", t, func() {
base, err := d.Base(context.Background(), 123)
convey.So(err, convey.ShouldBeNil)
convey.So(base, convey.ShouldNotBeNil)
})
}
func TestExp(t *testing.T) {
convey.Convey("Exp", t, func() {
exp, err := d.Exp(context.Background(), 123)
convey.So(err, convey.ShouldBeNil)
convey.So(exp, convey.ShouldNotBeNil)
})
}
func TestMoral(t *testing.T) {
convey.Convey("Moral", t, func() {
moral, err := d.Moral(context.Background(), 123)
convey.So(err, convey.ShouldBeNil)
convey.So(moral, convey.ShouldNotBeNil)
})
}
func TestDao_BatchUserAddit(t *testing.T) {
convey.Convey("BatchUserAddit", t, func() {
userAddits, err := d.BatchUserAddit(context.Background(), []int64{5, 13, 3})
convey.So(err, convey.ShouldBeNil)
convey.So(userAddits, convey.ShouldNotBeNil)
})
}
func TestDao_UpName(t *testing.T) {
convey.Convey("UpName", t, func() {
name := fmt.Sprintf("100_Bili_%v", time.Now().Unix())
err := d.UpName(context.Background(), 100, name)
convey.So(err, convey.ShouldBeNil)
})
}
func TestDao_UpSign(t *testing.T) {
convey.Convey("UpSign", t, func() {
sign := fmt.Sprintf("签名%v", time.Now().Unix())
err := d.UpSign(context.Background(), 100, sign)
convey.So(err, convey.ShouldBeNil)
})
}
func TestDao_UpFace(t *testing.T) {
convey.Convey("UpFace", t, func() {
face := fmt.Sprintf("testFace%v.jpg", time.Now().Unix())
err := d.UpFace(context.Background(), 100, face)
convey.So(err, convey.ShouldBeNil)
})
}
func TestDao_PubExpMsg(t *testing.T) {
convey.Convey("PubExpMsg", t, func() {
msg := &model.AddExpMsg{
Mid: 1,
IP: "127.0.0.1",
Ts: time.Now().Unix(),
Event: "test",
}
err := d.PubExpMsg(context.Background(), msg)
convey.So(err, convey.ShouldBeNil)
})
}
func TestDao_UserAddit(t *testing.T) {
convey.Convey("UserAddit", t, func() {
userAddit, err := d.UserAddit(context.Background(), 5)
convey.So(err, convey.ShouldBeNil)
convey.So(userAddit, convey.ShouldNotBeNil)
})
}
func TestDao_UpAdditRemark(t *testing.T) {
convey.Convey("UpAdditRemark", t, func() {
remark := fmt.Sprintf("remark%v", time.Now().Unix())
err := d.UpAdditRemark(context.Background(), 27515431, remark)
convey.So(err, convey.ShouldBeNil)
})
}

View File

@@ -0,0 +1,84 @@
package dao
import (
"bytes"
"context"
"crypto/sha1"
"encoding/hex"
"encoding/json"
"net/http"
"sort"
"strings"
"go-common/library/log"
"github.com/pkg/errors"
)
const (
_privateKey = "37ba757817b4e9c45c7e97f6ed5eee4e1c7bac52"
_publicKey = "71f079db59672ecec5b8d6f252c4b59ab2a8a227mainsite@bilibili.com"
)
// MerakNotify send notify
func (d *Dao) MerakNotify(ctx context.Context, title, content string) error {
params := map[string]string{
"Action": "CreateWechatMessage",
"PublicKey": _publicKey,
"UserName": strings.Join(d.c.ReviewNotify.Users, ","),
"Title": title,
"Content": content,
"TreeId": "",
}
sign, err := MerakSign(params)
if err != nil {
log.Error("Failed to sign params: %+v: %+v", params, err)
return err
}
params["Signature"] = sign
b, err := json.Marshal(params)
if err != nil {
return errors.WithStack(err)
}
req, err := http.NewRequest(http.MethodPost, d.merakURL, bytes.NewReader(b))
if err != nil {
return errors.WithStack(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
res := struct {
Action string `json:"Action"`
RetCode int `json:"RetCode"`
Data []string `json:"Data"`
}{}
if err = d.httpClient.Do(ctx, req, &res); err != nil {
return err
}
if res.RetCode != 0 {
err := errors.Errorf("Merak error: %d", res.RetCode)
log.Error("Failed to send notify by merak with params: %+v: %+v", string(b), err)
return err
}
return nil
}
// MerakSign is
func MerakSign(params map[string]string) (string, error) {
keys := make([]string, 0, len(params))
for k := range params {
keys = append(keys, k)
}
sort.Strings(keys)
buf := bytes.Buffer{}
for _, k := range keys {
buf.WriteString(k + params[k])
}
h := sha1.New()
if _, err := h.Write(buf.Bytes()); err != nil {
return "", errors.WithStack(err)
}
if _, err := h.Write([]byte(_privateKey)); err != nil {
return "", errors.WithStack(err)
}
sum := h.Sum(nil)
return hex.EncodeToString(sum), nil
}

View File

@@ -0,0 +1,49 @@
package dao
import (
"context"
"strings"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoSendWechat(t *testing.T) {
convey.Convey("SendWechat", t, func(ctx convey.C) {
var (
content = "测试内容"
title = "测试标题"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.MerakNotify(context.Background(), content, title)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoGetMerakSign(t *testing.T) {
convey.Convey("sign", t, func(ctx convey.C) {
var (
params = map[string]string{
"Action": "CreateWechatMessage",
"PublicKey": _publicKey,
//"UserName": strings.Join(d.c.ReviewNotify.Users, ","),
"UserName": strings.Join([]string{"user1", "user2"}, ","),
"Title": "测试标题",
"Content": "测试内容",
"TreeId": "",
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1, err := MerakSign(params)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldEqual, "59cd4e74b225a7d326ee7d6c89bf27cf2f6015dc")
})
})
})
}

View File

@@ -0,0 +1,46 @@
package dao
import (
"context"
"net/url"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/xstr"
"github.com/pkg/errors"
)
const (
_msgURL = "/api/notify/send.user.notify.do"
)
// Message send message.
func (d *Dao) Message(c context.Context, title, msg string, mids []int64) (err error) {
return d.RawMessage(c, "2_2_2", title, msg, mids)
}
// RawMessage send message with mc.
func (d *Dao) RawMessage(c context.Context, mc string, title, msg string, mids []int64) (err error) {
params := url.Values{}
params.Set("type", "json")
params.Set("source", "2")
params.Set("mc", mc)
params.Set("title", title)
params.Set("data_type", "4")
params.Set("context", msg)
params.Set("mid_list", xstr.JoinInts(mids))
var res struct {
Code int `json:"code"`
}
if err = d.httpClient.Post(c, d.msgURL, "", params, &res); err != nil {
err = errors.Wrap(err, "dao send message")
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrapf(err, "message send failed,mid(%v)", mids)
return
}
log.Info("sendmessage mc:%s, mids:%v, title:%s, msg:%s", mc, mids, title, msg)
return
}

View File

@@ -0,0 +1,45 @@
package dao
import (
"context"
"gopkg.in/h2non/gock.v1"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoMessage(t *testing.T) {
convey.Convey("Message", t, func(ctx convey.C) {
var (
c = context.Background()
title = "abc test"
msg = "abc"
mids = []int64{112}
mc = "2_2_2"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
defer gock.OffAll()
httpMock("POST", d.msgURL).Reply(200).JSON(`{"code":0}`)
err := d.RawMessage(c, mc, title, msg, mids)
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoRawMessage(t *testing.T) {
convey.Convey("RawMessage", t, func(ctx convey.C) {
var (
c = context.Background()
mc = "2_2_2"
title = "abc test"
msg = "abc test"
mids = []int64{112}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
defer gock.OffAll()
httpMock("POST", d.msgURL).Reply(200).JSON(`{"code":0}`)
err := d.RawMessage(c, mc, title, msg, mids)
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,64 @@
package dao
import (
"context"
"go-common/app/admin/main/member/model"
"go-common/library/database/sql"
"github.com/pkg/errors"
)
const (
_monitorName = "user_monitor"
)
// Monitors is.
func (d *Dao) Monitors(ctx context.Context, mid int64, includeDeleted bool, pn, ps int) (mns []*model.Monitor, total int, err error) {
query := d.member.Table(_monitorName).Order("id DESC")
if !includeDeleted {
query = query.Where("is_deleted=?", false)
}
if mid > 0 {
query = query.Where("mid=?", mid)
}
query = query.Count(&total)
query = query.Offset((pn - 1) * ps).Limit(ps)
if err = query.Find(&mns).Error; err != nil {
if err == sql.ErrNoRows {
return []*model.Monitor{}, 0, nil
}
err = errors.Wrap(err, "monitors")
return
}
return
}
// AddMonitor is.
func (d *Dao) AddMonitor(ctx context.Context, mid int64, operator, remark string) error {
mn := &model.Monitor{
Mid: mid,
}
ups := map[string]interface{}{
"is_deleted": false,
"operator": operator,
"remark": remark,
}
if err := d.member.Table(_monitorName).Where("mid=?", mid).Assign(ups).FirstOrCreate(mn).Error; err != nil {
return errors.Wrap(err, "add monitor")
}
return nil
}
// DelMonitor is.
func (d *Dao) DelMonitor(ctx context.Context, mid int64, operator, remark string) error {
ups := map[string]interface{}{
"is_deleted": true,
"operator": operator,
"remark": remark,
}
if err := d.member.Table(_monitorName).Where("mid=?", mid).UpdateColumns(ups).Error; err != nil {
return errors.Wrap(err, "del monitor")
}
return nil
}

View File

@@ -0,0 +1,60 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoAddMonitor(t *testing.T) {
convey.Convey("AddMonitor", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
operator = "aa"
remark = "aa"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AddMonitor(c, mid, operator, remark)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoMonitors(t *testing.T) {
convey.Convey("Monitors", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
pn = int(0)
ps = int(10)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
mns, total, err := d.Monitors(c, mid, false, pn, ps)
ctx.Convey("Then err should be nil.mns,total should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(total, convey.ShouldNotBeNil)
ctx.So(mns, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDelMonitor(t *testing.T) {
convey.Convey("DelMonitor", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
operator = "aa"
remark = "aa"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DelMonitor(c, mid, operator, remark)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,186 @@
package dao
import (
"context"
"time"
"go-common/app/admin/main/member/model"
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
)
const (
_officialName = "user_official"
_officialDocName = "user_official_doc"
_officialDocAdditName = "user_official_doc_addit"
)
// Official is.
func (d *Dao) Official(ctx context.Context, mid int64) (off *model.Official, err error) {
off = &model.Official{}
if err = d.member.Table(_officialName).Where("mid=?", mid).Find(off).Error; err != nil {
err = errors.Wrap(err, "official docs")
}
return
}
// OfficialEdit is.
func (d *Dao) OfficialEdit(ctx context.Context, mid int64, role int8, title, desc string) (off *model.Official, err error) {
off = &model.Official{
Mid: mid,
}
attrs := map[string]interface{}{
"role": role,
"title": title,
"description": desc,
}
if err = d.member.Table(_officialName).Where("mid=?", mid).Assign(attrs).FirstOrCreate(off).Error; err != nil {
err = errors.Wrap(err, "official edit")
}
return
}
// Officials is.
func (d *Dao) Officials(ctx context.Context, mid int64, roles []int8, stime, etime time.Time, pn, ps int) (offs []*model.Official, total int, err error) {
where := "role in (?) AND ctime>? AND ctime<?"
if mid > 0 {
where = "mid=? AND " + where
err = d.member.Table(_officialName).Order("ctime DESC").Offset((pn-1)*ps).Limit(ps).Where(where, mid, roles, stime, etime).Find(&offs).Error
d.member.Table(_officialName).Where(where, mid, roles, stime, etime).Count(&total)
} else {
err = d.member.Table(_officialName).Order("ctime DESC").Offset((pn-1)*ps).Limit(ps).Where(where, roles, stime, etime).Find(&offs).Error
d.member.Table(_officialName).Where(where, roles, stime, etime).Count(&total)
}
if err != nil {
err = errors.Wrap(err, "official docs")
}
return
}
// OfficialDoc is.
func (d *Dao) OfficialDoc(ctx context.Context, mid int64) (off *model.OfficialDoc, err error) {
off = &model.OfficialDoc{OfficialExtra: &model.OfficialExtra{}}
if err = d.member.Table(_officialDocName).Where("mid=?", mid).First(off).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
err = errors.Wrap(err, "official doc")
off = nil
return
}
off.ParseExtra()
return
}
// OfficialDocs is.
func (d *Dao) OfficialDocs(ctx context.Context, mid int64, roles, states []int8, uname string, stime, etime time.Time, pn, ps int) (offs []*model.OfficialDoc, total int, err error) {
query := d.member.Table(_officialDocName).Order("submit_time DESC")
if uname != "" {
query = query.Where("uname=?", uname)
}
if mid > 0 {
query = query.Where("mid=?", mid)
}
query = query.Where("role IN (?)", roles).
Where("state IN (?)", states).
Where("ctime > ?", stime).
Where("ctime < ?", etime)
query.Count(&total)
if err = query.Offset((pn - 1) * ps).Limit(ps).Find(&offs).Error; err != nil {
err = errors.Wrap(err, "official docs")
return
}
for _, od := range offs {
od.ParseExtra()
}
return
}
// OfficialDocsByMids is.
func (d *Dao) OfficialDocsByMids(ctx context.Context, mids []int64) (map[int64]*model.OfficialDoc, error) {
ofl := make([]*model.OfficialDoc, 0, len(mids))
offs := make(map[int64]*model.OfficialDoc, len(mids))
if err := d.member.Table(_officialDocName).Where("mid IN (?)", mids).Find(&ofl).Error; err != nil {
err = errors.Wrap(err, "official docs")
return nil, err
}
for _, of := range ofl {
offs[of.Mid] = of
}
for _, od := range offs {
od.ParseExtra()
}
return offs, nil
}
// OfficialDocAudit is.
func (d *Dao) OfficialDocAudit(ctx context.Context, mid int64, state int8, uname string, isInternal bool, rejectReason string) (err error) {
ups := map[string]interface{}{
"state": state,
"uname": uname,
"is_internal": isInternal,
"reject_reason": rejectReason,
}
if err = d.member.Table(_officialDocName).Where("mid=?", mid).Updates(ups).Error; err != nil {
err = errors.Wrap(err, "official doc audit")
}
return
}
// OfficialDocEdit is.
func (d *Dao) OfficialDocEdit(ctx context.Context, mid int64, name string, role, state int8, title, desc, extra string, uname string, isInternal bool) (err error) {
off := &model.OfficialDoc{
Mid: mid,
SubmitSource: "admin",
}
ups := map[string]interface{}{
"state": state,
"role": role,
"name": name,
"title": title,
"description": desc,
"extra": extra,
"uname": uname,
"is_internal": isInternal,
}
if err = d.member.Table(_officialDocName).Where("mid=?", mid).Assign(ups).FirstOrCreate(off).Error; err != nil {
err = errors.Wrap(err, "official doc audit")
}
return
}
// OfficialDocSubmit is.
func (d *Dao) OfficialDocSubmit(ctx context.Context, mid int64, name string, role, state int8, title, desc, extra string, uname string, isInternal bool, submitSource string) (err error) {
off := &model.OfficialDoc{
Mid: mid,
}
ups := map[string]interface{}{
"state": state,
"role": role,
"name": name,
"title": title,
"description": desc,
"extra": extra,
"uname": uname,
"is_internal": isInternal,
"submit_source": submitSource,
}
if err = d.member.Table(_officialDocName).Where("mid=?", mid).Assign(ups).FirstOrCreate(off).Error; err != nil {
err = errors.Wrap(err, "official doc audit")
}
return
}
// OfficialDocAddits .
func (d *Dao) OfficialDocAddits(ctx context.Context, property string, vstring string) ([]*model.OfficialDocAddit, error) {
addits := make([]*model.OfficialDocAddit, 0)
err := d.member.Table(_officialDocAdditName).Where("property=? and vstring=?", property, vstring).Find(&addits).Error
if err != nil {
err = errors.Wrap(err, "find official doc addit error")
return nil, err
}
return addits, nil
}

View File

@@ -0,0 +1,80 @@
package dao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestOfficial(t *testing.T) {
convey.Convey("Official", t, func() {
o, err := d.Official(context.Background(), 123)
convey.So(err, convey.ShouldBeNil)
convey.So(o, convey.ShouldNotBeNil)
})
}
func TestOfficialEdit(t *testing.T) {
convey.Convey("OfficialEdit", t, func() {
o, err := d.OfficialEdit(context.Background(), 123, 1, "title", "desc")
convey.So(err, convey.ShouldBeNil)
convey.So(o, convey.ShouldNotBeNil)
})
}
func TestOfficials(t *testing.T) {
convey.Convey("Officials", t, func() {
o, total, err := d.Officials(context.Background(), 123, []int8{1}, time.Time{}, time.Now(), 1, 20)
convey.So(err, convey.ShouldBeNil)
convey.So(o, convey.ShouldNotBeNil)
convey.So(total, convey.ShouldBeGreaterThan, 0)
})
}
func TestOfficialDoc(t *testing.T) {
convey.Convey("OfficialDoc", t, func() {
o, err := d.OfficialDoc(context.Background(), 123)
convey.So(err, convey.ShouldBeNil)
convey.So(o, convey.ShouldNotBeNil)
})
}
func TestOfficialDocs(t *testing.T) {
convey.Convey("OfficialDocs", t, func() {
o, total, err := d.OfficialDocs(context.Background(), 123, []int8{1}, []int8{1}, "", time.Time{}, time.Now(), 1, 20)
convey.So(err, convey.ShouldBeNil)
convey.So(o, convey.ShouldNotBeNil)
convey.So(total, convey.ShouldBeGreaterThan, 0)
})
}
func TestOfficialDocAudit(t *testing.T) {
convey.Convey("OfficialDocAudit", t, func() {
err := d.OfficialDocAudit(context.Background(), 123, 1, "guan", true, "")
convey.So(err, convey.ShouldBeNil)
})
}
func TestOfficialDocEdit(t *testing.T) {
convey.Convey("OfficialDocEdit", t, func() {
err := d.OfficialDocEdit(context.Background(), 123, "guan", 1, 1, "title", "desc", "extra", "12121", true)
convey.So(err, convey.ShouldBeNil)
})
}
func TestOfficialDocsByMids(t *testing.T) {
convey.Convey("OfficialDocsByMids", t, func() {
res, err := d.OfficialDocsByMids(context.Background(), []int64{2, 3, 10, 12})
convey.So(err, convey.ShouldBeNil)
convey.So(len(res), convey.ShouldBeGreaterThan, 0)
})
}
func TestOfficialDocSubmit(t *testing.T) {
convey.Convey("OfficialDocSubmit", t, func() {
err := d.OfficialDocSubmit(context.Background(), 123, "guan", 1, 1, "title", "desc", "extra", "12121", true, "admin")
convey.So(err, convey.ShouldBeNil)
})
}

View File

@@ -0,0 +1,119 @@
package dao
import (
"context"
"go-common/app/admin/main/member/model"
"net/url"
"strconv"
"sync"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/xstr"
)
const (
_updateUname = "/intranet/acc/updateUname"
_queryByMids = "/intranet/acc/queryByMids"
)
// UpdateUname is.
func (d *Dao) UpdateUname(ctx context.Context, mid int64, name string) error {
ip := metadata.String(ctx, metadata.RemoteIP)
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("uname", name)
var res struct {
Code int `json:"code"`
}
if err := d.passportClient.Post(ctx, d.upUnameURL, ip, params, &res); err != nil {
return err
}
if res.Code != 0 {
log.Error("Failed to update uname(%+v) code(%+v)", params, res.Code)
return parsePassportEcode(res.Code)
}
return nil
}
func parsePassportEcode(pecode int) error {
switch pecode {
case -618:
return ecode.UpdateUnameRepeated
case -617:
return ecode.UpdateUnameHadLocked
case -601:
return ecode.UpdateUnameFormat
}
log.Error("Unrecognized passport ecode: %d", pecode)
return ecode.Int(pecode)
}
// PassportQueryByMids is.
func (d *Dao) PassportQueryByMids(ctx context.Context, mids []int64) (map[int64]*model.PassportQueryByMidResult, error) {
ip := metadata.String(ctx, metadata.RemoteIP)
params := url.Values{}
params.Set("mids", xstr.JoinInts(mids))
var res struct {
Code int `json:"code"`
Cards map[string]*model.PassportQueryByMidResult `json:"cards"`
}
if err := d.passportClient.Get(ctx, d.queryByMidsURL, ip, params, &res); err != nil {
return nil, err
}
if res.Code != 0 {
log.Error("Failed to QueryByMid(%+v) code(%+v)", params, res.Code)
return nil, ecode.Int(res.Code)
}
result := make(map[int64]*model.PassportQueryByMidResult, len(res.Cards))
for _, card := range res.Cards {
result[card.Mid] = card
}
return result, nil
}
// PassportQueryByMidsChunked is
func (d *Dao) PassportQueryByMidsChunked(ctx context.Context, mids []int64, chunkSize int) (map[int64]*model.PassportQueryByMidResult, error) {
chunkedMids := func() [][]int64 {
divided := make([][]int64, 0)
for i := 0; i < len(mids); i += chunkSize {
end := i + chunkSize
if end > len(mids) {
end = len(mids)
}
divided = append(divided, mids[i:end])
}
return divided
}()
lock := sync.Mutex{}
result := make(map[int64]*model.PassportQueryByMidResult, len(mids))
wg := sync.WaitGroup{}
for _, chunk := range chunkedMids {
wg.Add(1)
go func(chunk []int64) {
defer wg.Done()
res, err := d.PassportQueryByMids(ctx, chunk)
if err != nil {
log.Error("Failed to get passport query by mids: %+v: %+v", chunk, err)
return
}
lock.Lock()
for k, v := range res {
result[k] = v
}
lock.Unlock()
}(chunk)
}
wg.Wait()
return result, nil
}

View File

@@ -0,0 +1,58 @@
package dao
import (
"context"
"fmt"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
"gopkg.in/h2non/gock.v1"
)
func TestDaoUpdateUname(t *testing.T) {
convey.Convey("UpdateUname", t, func(ctx convey.C) {
var (
mid = int64(321)
name = fmt.Sprintf("321testName%v%v", time.Now().Minute(), time.Now().Second())
)
ctx.Convey("UpdateUname success", func(ctx convey.C) {
defer gock.OffAll()
httpMock("POST", d.upUnameURL).Reply(200).JSON(`{"code":0}`)
err := d.UpdateUname(context.Background(), mid, name)
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("UpdateUname failed", func(ctx convey.C) {
defer gock.OffAll()
httpMock("POST", d.upUnameURL).Reply(200).JSON(`{"code":500}`)
err := d.UpdateUname(context.Background(), mid, name)
ctx.So(err, convey.ShouldNotBeNil)
})
})
}
func TestDaoPassportQueryByMids(t *testing.T) {
convey.Convey("PassportQueryByMids", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p, err := d.PassportQueryByMids(context.Background(), []int64{1, 2, 3})
ctx.Convey("Then err should be nil.p should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoPassportQueryByMidsChunked(t *testing.T) {
convey.Convey("PassportQueryByMidsChunked", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p, err := d.PassportQueryByMidsChunked(context.Background(), []int64{1, 2, 3}, 50)
ctx.Convey("Then err should be nil.p should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,500 @@
package dao
import (
"context"
"encoding/base64"
"fmt"
"strings"
"time"
"go-common/app/admin/main/member/model"
"go-common/library/cache/memcache"
"go-common/library/log"
"github.com/pkg/errors"
)
var (
_reasonKey = "reason"
)
func realnameImageKey(IMGData string) string {
return fmt.Sprintf("realname_image_%s", IMGData)
}
// RealnameInfo is.
func (d *Dao) RealnameInfo(ctx context.Context, mid int64) (info *model.DBRealnameInfo, err error) {
info = &model.DBRealnameInfo{}
if err = d.memberRead.Table(info.TableName()).Where("mid = ?", mid).First(&info).Error; err != nil {
info = nil
err = errors.WithStack(err)
}
return
}
// BatchRealnameInfo is
func (d *Dao) BatchRealnameInfo(ctx context.Context, mids []int64) (map[int64]*model.DBRealnameInfo, error) {
find := make([]*model.DBRealnameInfo, 0, len(mids))
db := d.memberRead.Table("realname_info").Where("mid IN (?)", mids).Where("status=?", model.RealnameApplyStatePassed.DBStatus()).Find(&find)
if err := db.Error; err != nil {
return nil, err
}
result := make(map[int64]*model.DBRealnameInfo, len(find))
for _, ri := range find {
result[ri.MID] = ri
}
return result, nil
}
// RealnameInfoByCardMD5 is.
func (d *Dao) RealnameInfoByCardMD5(ctx context.Context, cardMD5 string, state int, channel uint8) (infos []*model.DBRealnameInfo, err error) {
infos = make([]*model.DBRealnameInfo, 0)
var info *model.DBRealnameInfo
db := d.memberRead.Table(info.TableName()).Where("card_md5 = ?", cardMD5).Where("channel = ?", channel)
if state >= 0 {
db = db.Where("status = ?", state)
}
if err = db.Find(&infos).Error; err != nil {
if !db.RecordNotFound() {
err = errors.Wrapf(err, "RealnameInfoByCardMD5")
return
}
err = nil
return
}
return
}
// UpdateRealnameAlipayApply is.
func (d *Dao) UpdateRealnameAlipayApply(ctx context.Context, id int64, adminID int64, adminName string, state int, reason string) (err error) {
var (
mld *model.DBRealnameAlipayApply
ups = map[string]interface{}{
"operator": adminName,
"operator_id": adminID,
"operator_time": time.Now(),
"status": state,
"reason": reason,
}
)
if err = d.member.Table(mld.TableName()).Where("id = ?", id).Updates(ups).Error; err != nil {
err = errors.Wrapf(err, "UpdateRealnameAlipayApply")
}
return
}
// UpdateRealnameInfo is.
func (d *Dao) UpdateRealnameInfo(ctx context.Context, mid int64, state int, reason string) (err error) {
var (
mld *model.DBRealnameInfo
ups = map[string]interface{}{
"status": state,
"reason": reason,
}
)
if err = d.member.Table(mld.TableName()).Where("mid = ?", mid).Updates(ups).Error; err != nil {
err = errors.Wrapf(err, "UpdateRealnameInfo")
}
return
}
// RealnameMainApply is.
func (d *Dao) RealnameMainApply(ctx context.Context, id int64) (apply *model.DBRealnameApply, err error) {
apply = &model.DBRealnameApply{
Status: model.RealnameApplyStateNone.DBStatus(),
}
if err = d.memberRead.Table(apply.TableName()).Where("id = ?", id).First(&apply).Error; err != nil {
err = errors.WithStack(err)
}
return
}
// RealnameAlipayApply is.
func (d *Dao) RealnameAlipayApply(ctx context.Context, id int64) (apply *model.DBRealnameAlipayApply, err error) {
apply = &model.DBRealnameAlipayApply{
Status: model.RealnameApplyStateNone.DBStatus(),
}
if err = d.memberRead.Table(apply.TableName()).Where("id = ?", id).First(&apply).Error; err != nil {
err = errors.WithStack(err)
}
return
}
// RealnameMainList is.
func (d *Dao) RealnameMainList(ctx context.Context, mids []int64, cardType int, country int, opName string, tsFrom, tsTo int64, state int, pn, ps int, isDesc bool) (list []*model.DBRealnameApply, total int, err error) {
var (
mdl *model.DBRealnameApply
)
db := d.memberRead.Table(mdl.TableName())
if state >= 0 {
db = db.Where("status = ?", state)
}
if len(mids) > 0 {
db = db.Where("mid in (?)", mids)
}
if cardType >= 0 {
db = db.Where("card_type = ?", cardType)
}
if country >= 0 {
db = db.Where("country = ?", country)
}
if opName != "" {
db = db.Where("operator = ?", opName)
}
if tsTo > 0 {
timeTo := time.Unix(tsTo, 0)
db = db.Where("mtime <= ?", timeTo)
}
if tsFrom > 0 {
timeFrom := time.Unix(tsFrom, 0)
db = db.Where("mtime >= ?", timeFrom)
}
if err = db.Count(&total).Error; err != nil {
err = errors.Wrapf(err, "realname apply list count")
return
}
mtimeSort := "mtime ASC"
if isDesc {
mtimeSort = "mtime DESC"
}
db = db.Order(mtimeSort).Offset((pn - 1) * ps).Limit(ps)
if err = db.Find(&list).Error; err != nil {
if !db.RecordNotFound() {
err = errors.Wrapf(err, "realname apply list")
return
}
err = nil
return
}
return
}
// RealnameAlipayList is.
func (d *Dao) RealnameAlipayList(ctx context.Context, mids []int64, tsFrom, tsTo int64, state int, pn, ps int, isDesc bool) (list []*model.DBRealnameAlipayApply, total int, err error) {
var (
mdl *model.DBRealnameAlipayApply
)
db := d.memberRead.Table(mdl.TableName())
if state >= 0 {
db = db.Where("status = ?", state)
}
if len(mids) > 0 {
db = db.Where("mid in (?)", mids)
}
if tsTo > 0 {
timeTo := time.Unix(tsTo, 0)
db = db.Where("mtime <= ?", timeTo)
}
if tsFrom > 0 {
timeFrom := time.Unix(tsFrom, 0)
db = db.Where("mtime >= ?", timeFrom)
}
if err = db.Count(&total).Error; err != nil {
err = errors.Wrapf(err, "realname apply list count")
return
}
mtimeSort := "mtime ASC"
if isDesc {
mtimeSort = "mtime DESC"
}
db = db.Order(mtimeSort).Offset((pn - 1) * ps).Limit(ps)
if err = db.Find(&list).Error; err != nil {
if !db.RecordNotFound() {
err = errors.Wrapf(err, "realname apply list")
return
}
err = nil
return
}
return
}
// RealnameSearchCards is.
func (d *Dao) RealnameSearchCards(ctx context.Context, cardMD5s []string) (list []*model.DBRealnameInfo, err error) {
var (
mdl *model.DBRealnameInfo
)
db := d.memberRead.Table(mdl.TableName()).Where("card_md5 in (?)", cardMD5s)
if err = db.Find(&list).Error; err != nil {
if !db.RecordNotFound() {
err = errors.Wrapf(err, "realname apply list")
return
}
err = nil
return
}
return
}
// UpdateRealnameMainApply .
func (d *Dao) UpdateRealnameMainApply(ctx context.Context, id int, state int, opname string, opid int64, optime time.Time, remark string) (err error) {
var (
mld *model.DBRealnameApply
ups = map[string]interface{}{
"operator": opname,
"operator_id": opid,
"operator_time": optime,
"remark": remark,
"remark_status": 1,
"status": state,
}
)
if err = d.member.Table(mld.TableName()).Where("id = ?", id).Updates(ups).Error; err != nil {
err = errors.Wrapf(err, "UpdateRealnameApply")
}
return
}
// UpdateOldRealnameApply .
func (d *Dao) UpdateOldRealnameApply(ctx context.Context, id int64, state int, opname string, opid int64, optime time.Time, remark string) (err error) {
var (
ups = map[string]interface{}{
"operater": opname,
// "operator_id": opid,
"operater_time": optime.Unix(),
"remark": remark,
"remark_status": 1,
"status": state,
}
)
if err = d.account.Table("dede_identification_card_apply").Where("id = ?", id).Updates(ups).Error; err != nil {
err = errors.Wrapf(err, "UpdateOldRealnameApply")
}
return
}
// RealnameApplyIMG .
func (d *Dao) RealnameApplyIMG(ctx context.Context, ids []int64) (imgMap map[int64]*model.DBRealnameApplyIMG, err error) {
var (
db = d.memberRead.Where("id in (?)", ids)
list []*model.DBRealnameApplyIMG
)
imgMap = make(map[int64]*model.DBRealnameApplyIMG)
if err = db.Find(&list).Error; err != nil {
if !db.RecordNotFound() {
err = errors.Wrapf(err, "RealnameApplyIMG")
return
}
err = nil
}
for _, l := range list {
imgMap[l.ID] = l
}
return
}
// RealnameApplyCount .
func (d *Dao) RealnameApplyCount(ctx context.Context, mid int64) (count int, err error) {
var (
ml *model.DBRealnameApply
aml *model.DBRealnameAlipayApply
tempCount int
db = d.memberRead.Table(ml.TableName()).Where("mid = ?", mid)
db2 = d.memberRead.Table(aml.TableName()).Where("mid = ?", mid)
)
if err = db.Count(&tempCount).Error; err != nil {
err = errors.WithStack(err)
return
}
count += tempCount
if err = db2.Count(&tempCount).Error; err != nil {
err = errors.WithStack(err)
return
}
count += tempCount
return
}
// RealnameReasonList .
func (d *Dao) RealnameReasonList(ctx context.Context) (list []string, total int, err error) {
var (
conf = &model.DBRealnameConfig{}
db = d.memberRead.Where("`key` = ?", _reasonKey).First(&conf)
)
if err = db.Error; err != nil {
if !db.RecordNotFound() {
err = errors.Wrapf(err, "RealnameReasonList")
return
}
err = nil
}
list = decodeReason(conf.Data)
total = len(list)
return
}
// UpdateRealnameReason .
func (d *Dao) UpdateRealnameReason(ctx context.Context, list []string) (err error) {
var (
conf *model.DBRealnameConfig
ups = map[string]interface{}{
"data": encodeReason(list),
}
)
if err = d.member.Table(conf.TableName()).Where("`key` = ?", _reasonKey).Updates(ups).Error; err != nil {
err = errors.Wrapf(err, "UpdateRealnameReason")
}
return
}
func encodeReason(list []string) (data string) {
raw := []byte(strings.Join(list, "(#=_=#)"))
return base64.StdEncoding.EncodeToString(raw)
}
func decodeReason(data string) (list []string) {
var (
raw []byte
err error
)
if raw, err = base64.StdEncoding.DecodeString(data); err != nil {
err = errors.WithStack(err)
log.Error("%+v", err)
return
}
list = strings.Split(string(raw), "(#=_=#)")
return
}
// AddRealnameIMG is
func (d *Dao) AddRealnameIMG(ctx context.Context, img *model.DBRealnameApplyIMG) error {
if err := d.member.Create(img).Error; err != nil {
return errors.WithStack(err)
}
return nil
}
// AddRealnameApply is
func (d *Dao) AddRealnameApply(ctx context.Context, apply *model.DBRealnameApply) error {
if err := d.member.Create(apply).Error; err != nil {
return errors.WithStack(err)
}
return nil
}
// SubmitRealnameInfo is
func (d *Dao) SubmitRealnameInfo(ctx context.Context, info *model.DBRealnameInfo) error {
ups := map[string]interface{}{
"channel": info.Channel,
"realname": info.Realname,
"country": info.Country,
"card_type": info.CardType,
"card": info.Card,
"card_md5": info.CardMD5,
"status": info.Status,
"reason": info.Reason,
}
if err := d.member.Table(info.TableName()).Where("mid=?", info.MID).Assign(ups).FirstOrCreate(info).Error; err != nil {
return errors.WithStack(err)
}
return nil
}
// GetRealnameImageCache is
func (d *Dao) GetRealnameImageCache(ctx context.Context, IMGData string) ([]byte, error) {
key := realnameImageKey(IMGData)
conn := d.memcache.Get(ctx)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
return nil, err
}
out := []byte{}
if err := conn.Scan(item, &out); err != nil {
return nil, err
}
return out, nil
}
// SetRealnameImageCache is
func (d *Dao) SetRealnameImageCache(ctx context.Context, IMGData string, data []byte) error {
key := realnameImageKey(IMGData)
conn := d.memcache.Get(ctx)
defer conn.Close()
return conn.Set(&memcache.Item{
Key: key,
Value: data,
Flags: memcache.FlagRAW | memcache.FlagGzip,
Expiration: 6 * 3600, // cache for 6 hours
})
}
// RecentRealnameApplyImg is
func (d *Dao) RecentRealnameApplyImg(ctx context.Context, duration time.Duration) ([]*model.DBRealnameApplyIMG, error) {
from := time.Now().Add(-duration)
result := []*model.DBRealnameApplyIMG{}
db := d.memberRead.Where("mtime>=?", from).Order("id desc").Find(&result)
if err := db.Error; err != nil {
return nil, err
}
return result, nil
}
// RejectRealnameMainApply is
func (d *Dao) RejectRealnameMainApply(ctx context.Context, mid int64, opname string, opid int64, remark string) (err error) {
var (
mld *model.DBRealnameApply
ups = map[string]interface{}{
"operator": opname,
"operator_id": opid,
"operator_time": time.Now(),
"remark": remark,
"remark_status": 1,
"status": model.RealnameApplyStateRejective.DBStatus(),
}
)
if err = d.member.Table(mld.TableName()).
Where("mid = ?", mid).
Where("status = ?", model.RealnameApplyStatePassed.DBStatus()).
Updates(ups).Error; err != nil {
err = errors.Wrapf(err, "RejectRealnameMainApply")
}
return
}
// RejectRealnameAlipayApply is
func (d *Dao) RejectRealnameAlipayApply(ctx context.Context, mid int64, opname string, opid int64, reason string) (err error) {
var (
mld *model.DBRealnameAlipayApply
ups = map[string]interface{}{
"operator": opname,
"operator_id": opid,
"operator_time": time.Now(),
"status": model.RealnameApplyStateRejective.DBStatus(),
"reason": reason,
}
)
if err = d.member.Table(mld.TableName()).
Where("mid = ?", mid).
Where("status = ?", model.RealnameApplyStatePassed.DBStatus()).
Updates(ups).Error; err != nil {
err = errors.Wrapf(err, "UpdateRealnameAlipayApply")
}
return
}
// LastPassedRealnameMainApply is
func (d *Dao) LastPassedRealnameMainApply(ctx context.Context, mid int64) (*model.DBRealnameApply, error) {
apply := &model.DBRealnameApply{}
if err := d.member.Table("realname_apply").Where("mid=?", mid).
Where("status=?", model.RealnameApplyStatePassed.DBStatus()).
Order("id DESC").Limit(1).Last(apply).Error; err != nil {
return nil, err
}
return apply, nil
}
// LastPassedRealnameAlipayApply is
func (d *Dao) LastPassedRealnameAlipayApply(ctx context.Context, mid int64) (*model.DBRealnameAlipayApply, error) {
apply := &model.DBRealnameAlipayApply{}
if err := d.member.Table("realname_alipay_apply").Where("mid=?", mid).
Where("status=?", model.RealnameApplyStatePassed.DBStatus()).
Order("id DESC").Limit(1).Last(apply).Error; err != nil {
return nil, err
}
return apply, nil
}

View File

@@ -0,0 +1,25 @@
package dao
import (
"context"
"go-common/app/admin/main/member/model"
"github.com/pkg/errors"
)
// AddOldRealnameIMG is
func (d *Dao) AddOldRealnameIMG(ctx context.Context, img *model.DeDeIdentificationCardApplyImg) error {
if err := d.account.Create(img).Error; err != nil {
return errors.WithStack(err)
}
return nil
}
// AddOldRealnameApply is
func (d *Dao) AddOldRealnameApply(ctx context.Context, apply *model.DeDeIdentificationCardApply) error {
if err := d.account.Create(apply).Error; err != nil {
return errors.WithStack(err)
}
return nil
}

View File

@@ -0,0 +1,169 @@
package dao
import (
"context"
"testing"
"time"
"go-common/app/admin/main/member/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestRealnameList(t *testing.T) {
Convey("Realname list", t, func() {
var (
mids = []int64{46333}
cardType = 0
country = 0
opName = ""
tsFrom = int64(1528023084)
tsTo = time.Now().Unix()
state = 2
pn, ps = 1, 20
)
list, total, err := d.RealnameMainList(context.Background(), mids, cardType, country, opName, tsFrom, tsTo, state, pn, ps, false)
So(err, ShouldBeNil)
So(list, ShouldNotBeNil)
So(total, ShouldNotBeNil)
})
}
func TestRealnameReason(t *testing.T) {
Convey("Realname reason", t, func() {
var (
list = []string{
"+1s",
"蛤",
"苟利国家",
"19260817",
}
)
err := d.UpdateRealnameReason(context.Background(), list)
So(err, ShouldBeNil)
list2, total, err := d.RealnameReasonList(context.Background())
So(err, ShouldBeNil)
So(total, ShouldEqual, len(list))
So(list2, ShouldResemble, list)
})
}
func TestRealnameApplyCount(t *testing.T) {
Convey("Realname apply count", t, func() {
var (
mid = int64(1)
)
count, err := d.RealnameApplyCount(context.Background(), mid)
So(err, ShouldBeNil)
So(count, ShouldNotBeNil)
})
}
func TestRealnameApply(t *testing.T) {
Convey("Realname apply", t, func() {
var (
id = int64(1)
)
apply, err := d.RealnameMainApply(context.Background(), id)
So(err, ShouldBeNil)
So(apply, ShouldNotBeNil)
})
}
func TestRealnameApplyUpdate(t *testing.T) {
Convey("Realname apply update", t, func() {
var (
id = 1
state = 2
opname = "ut"
opid = int64(233)
optime = time.Now()
remark = "ut_reason"
)
err := d.UpdateRealnameMainApply(context.Background(), id, state, opname, opid, optime, remark)
So(err, ShouldBeNil)
})
}
func TestRealnameAlipayApply(t *testing.T) {
Convey("Realname alipay apply", t, func() {
var (
id = int64(1)
)
apply, err := d.RealnameAlipayApply(context.Background(), id)
So(err, ShouldBeNil)
t.Log(apply)
})
}
func TestRealnameUpdateAlipayApply(t *testing.T) {
Convey("Realname update alipay apply", t, func() {
var (
id = int64(1)
)
err := d.UpdateRealnameAlipayApply(context.Background(), id, 1, "someone", 2, "ut")
So(err, ShouldBeNil)
})
}
func TestUpdateRealnameInfo(t *testing.T) {
Convey("Realname update realname info", t, func() {
var (
id = int64(1)
)
err := d.UpdateRealnameInfo(context.Background(), id, 2, "ut")
So(err, ShouldBeNil)
})
}
func TestAddRealnameIMG(t *testing.T) {
Convey("AddRealnameIMG", t, func() {
err := d.AddRealnameIMG(context.Background(), &model.DBRealnameApplyIMG{IMGData: "testing"})
So(err, ShouldBeNil)
})
}
func TestAddRealnameApply(t *testing.T) {
Convey("AddRealnameApply", t, func() {
err := d.AddRealnameApply(context.Background(), &model.DBRealnameApply{MID: 1})
So(err, ShouldBeNil)
})
}
func TestBatchRealnameInfo(t *testing.T) {
Convey("BatchRealnameInfo", t, func() {
res, err := d.BatchRealnameInfo(context.Background(), []int64{1, 2, 3})
So(res, ShouldNotBeNil)
So(err, ShouldBeNil)
})
}
func TestRejectRealnameMainApply(t *testing.T) {
Convey("RejectRealnameMainApply", t, func() {
err := d.RejectRealnameMainApply(context.Background(), 1, "admin", 1, "test")
So(err, ShouldBeNil)
})
}
func TestRejectRealnameAlipayApply(t *testing.T) {
Convey("RejectRealnameAlipayApply", t, func() {
err := d.RejectRealnameAlipayApply(context.Background(), 1, "admin", 1, "test")
So(err, ShouldBeNil)
})
}
func TestAddOldRealnameIMG(t *testing.T) {
Convey("AddOldRealnameIMG", t, func() {
err := d.AddOldRealnameIMG(context.Background(), &model.DeDeIdentificationCardApplyImg{IMGData: "/test"})
So(err, ShouldBeNil)
})
}
func TestAddOldRealnameApply(t *testing.T) {
Convey("AddOldRealnameApply", t, func() {
err := d.AddOldRealnameApply(context.Background(), &model.DeDeIdentificationCardApply{MID: 1})
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,46 @@
package dao
import (
"context"
"fmt"
"time"
"go-common/library/cache/redis"
"go-common/library/log"
"go-common/library/net/ip"
)
func reviewAuditNotifyLockKey(t time.Time) string {
prefix := t.Format("2006-01-02-15")
if t.Minute() < 30 {
return fmt.Sprintf("review_notify_%s_00", prefix)
}
return fmt.Sprintf("review_notify_%s_30", prefix)
}
func (d *Dao) pingRedis(c context.Context) error {
conn := d.redis.Get(c)
defer conn.Close()
_, err := conn.Do("SET", "ping", "pong")
return err
}
// TryLockReviewNotify is
func (d *Dao) TryLockReviewNotify(c context.Context, t time.Time) (bool, error) {
key := reviewAuditNotifyLockKey(t)
conn := d.redis.Get(c)
defer conn.Close()
locked, err := redis.Bool(conn.Do("SETNX", key, fmt.Sprintf("%s::%s", ip.InternalIP(), t)))
if err != nil {
return false, err
}
if !locked {
return false, nil
}
if _, err := conn.Do("EXPIRE", key, 60*60); err != nil {
log.Error("Failed to set expire on key: %s: %+v", key, err)
// return
}
return locked, nil
}

View File

@@ -0,0 +1,47 @@
package dao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoTryLockReviewNotify(t *testing.T) {
convey.Convey("TryLockReviewNotify", t, func() {
now := time.Now()
no := time.Date(2018, 1, 7, 20, now.Minute(), now.Second(), 651387237, time.UTC)
p1, err := d.TryLockReviewNotify(context.Background(), no)
convey.So(err, convey.ShouldBeNil)
convey.So(p1, convey.ShouldNotBeNil)
})
}
//func TestDaoreviewAuditNotifyLockKey(t *testing.T) {
// convey.Convey("reviewAuditNotifyLockKey", t, func(ctx convey.C) {
// var (
// no = time.Now()
// )
// ctx.Convey("When everything goes positive", func(ctx convey.C) {
// p1 := reviewAuditNotifyLockKey(no)
// ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
// ctx.So(p1, 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,238 @@
package dao
import (
"context"
"fmt"
"go-common/app/admin/main/member/model"
"go-common/library/database/sql"
xtime "go-common/library/time"
"github.com/pkg/errors"
)
const (
_reviewName = "user_property_review"
)
// Reviews is. todo delete
func (d *Dao) Reviews(ctx context.Context, mid int64, property []int8, state []int8, isMonitor, isDesc bool, operator string, stime, etime xtime.Time, pn, ps int) ([]*model.UserPropertyReview, int, error) {
from, to, err := d.prepareReviewRange(ctx, stime, etime)
if err != nil {
return nil, 0, err
}
order := "asc"
if isDesc {
order = "desc"
}
rws := []*model.UserPropertyReview{}
total := 0
query := d.member.Table(_reviewName).
Order("id "+order).
Where("id>=?", from).
Where("id<=?", to).
Where("is_monitor=?", isMonitor)
if mid > 0 {
query = query.Where("mid=?", mid)
}
if len(property) > 0 {
query = query.Where("property IN (?)", property)
}
if operator != "" {
query = query.Where("operator=?", operator)
}
if len(state) > 0 {
query = query.Where("state IN (?)", state)
}
query = query.Count(&total)
query = query.Offset((pn - 1) * ps).Limit(ps)
if err := query.Find(&rws).Error; err != nil {
if err == sql.ErrNoRows {
return []*model.UserPropertyReview{}, 0, nil
}
err = errors.Wrap(err, "reviews")
return nil, 0, err
}
for _, rw := range rws {
if rw.Property == model.ReviewPropertyFace {
rw.BuildFaceURL()
}
}
return rws, total, nil
}
func (d *Dao) prepareReviewRange(ctx context.Context, stime, etime xtime.Time) (int64, int64, error) {
// from id
rw := &model.UserPropertyReview{}
if err := d.member.Table(_reviewName).
Select("id").
Where("ctime>?", stime).
Order("ctime asc").
Limit(1).
Find(rw).Error; err != nil {
return 0, 0, err
}
from := rw.ID
// to id
rw = &model.UserPropertyReview{}
if err := d.member.Table(_reviewName).
Select("id").
Where("ctime<?", etime).
Order("ctime desc").
Limit(1).
Find(rw).Error; err != nil {
return 0, 0, err
}
to := rw.ID
return from, to, nil
}
// ReviewAudit is.
func (d *Dao) ReviewAudit(ctx context.Context, id []int64, state int8, remark, operator string) error {
ups := map[string]interface{}{
"state": state,
"remark": remark,
"operator": operator,
}
if err := d.member.Table(_reviewName).Where("id IN (?)", id).Where("state=?", model.ReviewStateWait).UpdateColumns(ups).Error; err != nil {
return errors.Wrap(err, "review audit")
}
return nil
}
// Review is.
func (d *Dao) Review(ctx context.Context, id int64) (*model.UserPropertyReview, error) {
r := &model.UserPropertyReview{}
if err := d.member.Table(_reviewName).Where("id=?", id).First(r).Error; err != nil {
return nil, err
}
return r, nil
}
// ReviewByIDs is.
func (d *Dao) ReviewByIDs(ctx context.Context, ids []int64, state []int8) ([]*model.UserPropertyReview, error) {
rws := []*model.UserPropertyReview{}
query := d.member.Table(_reviewName).Where("id IN (?)", ids)
if len(state) > 0 {
query = query.Where("state in (?)", state)
}
if err := query.Find(&rws).Error; err != nil {
if err == sql.ErrNoRows {
return []*model.UserPropertyReview{}, nil
}
err = errors.Wrap(err, "review by ids")
return nil, err
}
return rws, nil
}
// UpdateReviewFace is.
func (d *Dao) UpdateReviewFace(ctx context.Context, id int64, face string) error {
ups := map[string]interface{}{
"new": face,
}
if err := d.member.Table(_reviewName).
Where("id=?", id).
Where("property=?", model.ReviewPropertyFace).
Update(ups).Error; err != nil {
return errors.WithStack(err)
}
return nil
}
// MvArchivedFaceToPriv mvArchivedFaceToPriv.
func (d *Dao) MvArchivedFaceToPriv(ctx context.Context, face, privFace, operator, remark string) error {
ups := map[string]interface{}{
"new": privFace,
"remark": fmt.Sprintf("将归档图片移动到新bucket, face: %s,remark: %s,operator: %s", face, remark, operator),
}
if err := d.member.Table(_reviewName).
Where("new=?", face).
Where("property=?", model.ReviewPropertyFace).
Where("state=?", model.ReviewStateArchived).
Where("is_monitor=?", false).
Update(ups).Error; err != nil {
return errors.WithStack(err)
}
return nil
}
// IncrFaceReject incrFaceReject.
func (d *Dao) IncrFaceReject(ctx context.Context, mid int64) error {
if err := d.member.Exec("INSERT INTO user_addit (mid,face_reject)VALUES(?,1) ON DUPLICATE KEY UPDATE face_reject=face_reject+1", mid).Error; err != nil {
return errors.Wrapf(err, "mid: %d", mid)
}
return nil
}
// IncrViolationCount is.
func (d *Dao) IncrViolationCount(ctx context.Context, mid int64) error {
if err := d.member.Exec("INSERT INTO user_addit (mid,violation_count)VALUES(?,1) ON DUPLICATE KEY UPDATE violation_count=violation_count+1", mid).Error; err != nil {
return errors.Wrapf(err, "mid: %d", mid)
}
return nil
}
// FaceAutoPass is.
func (d *Dao) FaceAutoPass(ctx context.Context, ids []int64, etime xtime.Time) (err error) {
ups := map[string]interface{}{
"operator": "system/auto",
"remark": "48 小时未处理自动通过",
"state": model.ReviewStatePass,
}
if err = d.member.Table(_reviewName).
Where("state in (?)", []int8{model.ReviewStateWait, model.ReviewStateQueuing}).
Where("id in (?)", ids).
Where("mtime<?", etime).
Update(ups).Error; err != nil {
err = errors.WithStack(err)
return
}
return
}
// UpdateRemark is.
func (d *Dao) UpdateRemark(ctx context.Context, id int64, remark string) (err error) {
ups := map[string]interface{}{
"remark": remark,
}
if err := d.member.Table(_reviewName).
Where("id=?", id).
Update(ups).Error; err != nil {
return errors.WithStack(err)
}
return nil
}
//QueuingFaceReviewsByTime is.
func (d *Dao) QueuingFaceReviewsByTime(c context.Context, stime, etime xtime.Time) ([]*model.UserPropertyReview, error) {
rws := []*model.UserPropertyReview{}
if err := d.member.Table(_reviewName).
Where("ctime>? ", stime).
Where("ctime<? ", etime).
Where("property=?", model.ReviewPropertyFace).
Where("state=?", model.ReviewStateQueuing).
Find(&rws).Error; err != nil {
return nil, err
}
return rws, nil
}
//AuditQueuingFace is
func (d *Dao) AuditQueuingFace(c context.Context, id int64, remark string, state int8) error {
ups := map[string]interface{}{
"remark": remark,
"state": state,
"operator": "system",
}
if err := d.member.Table(_reviewName).
Where("id=?", id).
Where("state=?", model.ReviewStateQueuing).
Update(ups).Error; err != nil {
return errors.WithStack(err)
}
return nil
}

View File

@@ -0,0 +1,115 @@
package dao
import (
"context"
"testing"
"time"
xtime "go-common/library/time"
. "github.com/smartystreets/goconvey/convey"
)
func TestDao_MvArchivedFaceToPri(t *testing.T) {
Convey("MvArchivedFaceToPri", t, func() {
err := d.MvArchivedFaceToPriv(context.Background(), "/bfs/face/7e68723b9d3664ac3773c1f3c26d5e2bfabc0f23.jpg", "/bfs/face/7e68723b9d3664ac3773c1f3c26d5e2bfabc0f21.jpg", "sys", "")
So(err, ShouldBeNil)
})
}
func TestDao_IncrFaceReject(t *testing.T) {
Convey("IncrFaceReject", t, func() {
err := d.IncrFaceReject(context.Background(), 2)
So(err, ShouldBeNil)
})
}
func TestDao_IncrViolationCount(t *testing.T) {
Convey("IncrViolationCount", t, func() {
err := d.IncrViolationCount(context.Background(), 2)
So(err, ShouldBeNil)
})
}
func TestDao_FaceAutoPass(t *testing.T) {
Convey("FaceAutoPass", t, func() {
t := xtime.Time(time.Now().Unix())
err := d.FaceAutoPass(context.Background(), []int64{1}, t)
So(err, ShouldBeNil)
})
}
func TestDao_prepareReviewRange(t *testing.T) {
Convey("prepareReviewRange", t, func() {
stime := time.Date(0, 0, 0, 0, 0, 0, 0, time.Local).Unix()
etime := time.Now().Unix()
s, e, err := d.prepareReviewRange(context.Background(), xtime.Time(stime), xtime.Time(etime))
So(err, ShouldBeNil)
So(s, ShouldNotBeEmpty)
So(e, ShouldNotBeEmpty)
})
}
func TestDao_UpdateRemark(t *testing.T) {
Convey("UpdateRemark", t, func() {
err := d.UpdateRemark(context.Background(), 1, "12334")
So(err, ShouldBeNil)
})
}
func TestDao_QueuingFaceReviewsByTime(t *testing.T) {
Convey("QueuingFaceReviewsByTime", t, func() {
stime := time.Date(2018, 10, 1, 0, 0, 0, 0, time.Local).Unix()
etime := time.Date(2018, 11, 1, 0, 0, 0, 0, time.Local).Unix()
rws, err := d.QueuingFaceReviewsByTime(context.Background(), xtime.Time(stime), xtime.Time(etime))
So(err, ShouldBeNil)
// FIXME : UAT上全时间段查询不到该类数据
So(rws, ShouldBeEmpty)
})
}
func TestDao_ReviewByIDs(t *testing.T) {
Convey("ReviewByIDs", t, func() {
rws, err := d.ReviewByIDs(context.Background(), []int64{1, 2}, []int8{})
So(err, ShouldBeNil)
So(rws, ShouldNotBeEmpty)
})
}
func TestDao_Reviews(t *testing.T) {
Convey("Reviews", t, func() {
rws, total, err := d.Reviews(context.Background(), 2231365, []int8{1}, []int8{0, 1, 2}, true, true, "", 1530542443, 1540910443, 1, 10)
So(err, ShouldBeNil)
So(total, ShouldNotBeNil)
So(rws, ShouldNotBeNil)
})
}
func TestDao_ReviewAudit(t *testing.T) {
Convey("ReviewAudit", t, func() {
err := d.ReviewAudit(context.Background(), []int64{2231365, 2231365}, 0, "test", "test")
So(err, ShouldBeNil)
})
}
func TestDao_Review(t *testing.T) {
Convey("Review", t, func() {
userPropertyReview, err := d.Review(context.Background(), 1)
So(err, ShouldBeNil)
So(userPropertyReview, ShouldNotBeNil)
})
}
func TestDao_UpdateReviewFace(t *testing.T) {
Convey("UpdateReviewFace", t, func() {
err := d.UpdateReviewFace(context.Background(), 2231365, "face test")
So(err, ShouldBeNil)
})
}
func TestDao_AuditQueuingFace(t *testing.T) {
Convey("Review", t, func() {
err := d.AuditQueuingFace(context.Background(), 2231365, "face test", 0)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,163 @@
package dao
import (
"context"
"fmt"
"regexp"
"strconv"
"strings"
"time"
"go-common/app/admin/main/member/model"
"go-common/library/database/elastic"
"go-common/library/log"
"github.com/pkg/errors"
)
var (
_numPattern = regexp.MustCompile(`^\d+$`)
)
func allnum(s string) bool {
return _numPattern.MatchString(s)
}
// SearchMember is.
func (d *Dao) SearchMember(ctx context.Context, arg *model.ArgList) (*model.SearchMemberResult, error) {
r := d.es.NewRequest("member_user").
Fields("mid", "name").
Index("user_base").
Order("mid", elastic.OrderAsc).
Ps(int(arg.PS)).
Pn(int(arg.PN))
if arg.Mid != 0 {
r.WhereEq("mid", arg.Mid)
}
if arg.Keyword != "" {
fields := []string{"name"}
if allnum(arg.Keyword) {
fields = append(fields, "mid")
}
r.WhereLike(fields, []string{arg.Keyword}, true, elastic.LikeLevelLow)
}
result := &model.SearchMemberResult{}
if err := r.Scan(ctx, &result); err != nil {
return nil, errors.WithStack(err)
}
return result, nil
}
// SearchLog is.
func (d *Dao) SearchLog(ctx context.Context, uid, oid int64, uname, action string) (*model.SearchLogResult, error) {
nowYear := time.Now().Year()
index := []string{
fmt.Sprintf("log_audit_121_%d", nowYear),
fmt.Sprintf("log_audit_121_%d", nowYear-1),
}
r := d.es.NewRequest("log_audit").
Index(index...).
Fields("uid", "uname", "oid", "type", "action", "str_0", "str_1", "str_2", "int_0", "int_1", "int_2", "ctime", "extra_data").
Order("ctime", elastic.OrderDesc)
// 默认查询的是第一页每夜10条记录
if uid > 0 {
r.WhereEq("uid", strconv.FormatInt(uid, 10))
}
if oid > 0 {
r.WhereEq("oid", strconv.FormatInt(oid, 10))
}
if uname != "" {
r.WhereEq("uname", uname)
}
if action != "" {
r.WhereIn("action", strings.Split(action, ","))
}
result := &model.SearchLogResult{}
if err := r.Scan(ctx, result); err != nil {
log.Error("Failed to SearchLog: Scan params(%s) error(%+v)", r.Params(), err)
return nil, err
}
return result, nil
}
// SearchFaceCheckRes is.
func (d *Dao) SearchFaceCheckRes(ctx context.Context, fileName string) (*model.SearchLogResult, error) {
index := fmt.Sprintf("log_audit_161_%s", time.Now().Format("2006_01"))
r := d.es.NewRequest("log_audit").
Index(index).
Fields("uid", "uname", "oid", "type", "action", "str_0", "str_1", "str_2", "int_0", "int_1", "int_2", "ctime", "extra_data").
WhereEq("str_1", "face").
WhereEq("str_2", fileName).
Order("ctime", elastic.OrderDesc).
Pn(1).
Ps(1)
result := &model.SearchLogResult{}
if err := r.Scan(ctx, result); err != nil {
log.Error("Failed to SearchFaceCheckRes: Scan params(%s) error(%+v)", r.Params(), err)
return nil, err
}
return result, nil
}
// SearchUserAuditLog is.
func (d *Dao) SearchUserAuditLog(ctx context.Context, mid int64) (*model.SearchLogResult, error) {
nowYear := time.Now().Year()
index := []string{
fmt.Sprintf("log_audit_121_%d", nowYear),
fmt.Sprintf("log_audit_121_%d", nowYear-1),
}
r := d.es.NewRequest("log_audit").
Index(index...).
Fields("uid", "uname", "oid", "type", "action", "str_0", "str_1", "str_2", "int_0", "int_1", "int_2", "ctime", "extra_data").
WhereEq("action", "base_audit").
WhereEq("oid", strconv.FormatInt(mid, 10)).
Order("ctime", elastic.OrderDesc).
Pn(1).
Ps(5)
result := &model.SearchLogResult{}
if err := r.Scan(ctx, result); err != nil {
log.Error("Failed to SearchUserAuditLog: Scan params(%s) error(%+v)", r.Params(), err)
return nil, err
}
return result, nil
}
// SearchUserPropertyReview is.
func (d *Dao) SearchUserPropertyReview(ctx context.Context, mid int64, property []int, state []int, isMonitor, isDesc bool, operator, stime, etime string, pn, ps int) (*model.SearchUserPropertyReviewResult, error) {
order := elastic.OrderAsc
if isDesc {
order = elastic.OrderDesc
}
monitor := 0
if isMonitor {
monitor = 1
}
r := d.es.NewRequest("user_property_review").
Fields("id").
Index("user_property_review").
WhereEq("is_monitor", monitor).
WhereRange("ctime", stime, etime, elastic.RangeScopeLcRc).
Order("id", order).
Ps(ps).
Pn(pn)
if mid > 0 {
r.WhereEq("mid", mid)
}
if operator != "" {
r.WhereEq("operator", operator)
}
if len(property) > 0 {
r.WhereIn("property", property)
}
if len(state) > 0 {
r.WhereIn("state", state)
}
result := &model.SearchUserPropertyReviewResult{}
if err := r.Scan(ctx, result); err != nil {
return nil, errors.WithStack(err)
}
return result, nil
}

View File

@@ -0,0 +1,53 @@
package dao
import (
"context"
"testing"
"time"
"go-common/app/admin/main/member/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoSearchMember(t *testing.T) {
convey.Convey("SearchMember", t, func() {
result, err := d.SearchMember(context.Background(), &model.ArgList{Mid: 627272, PN: 1, PS: 10})
convey.So(err, convey.ShouldBeNil)
convey.So(result, convey.ShouldNotBeNil)
})
}
func TestSearchLog(t *testing.T) {
convey.Convey("SearchLog", t, func() {
result, err := d.SearchLog(context.Background(), 1164, 0, "", "")
convey.So(err, convey.ShouldBeNil)
convey.So(result, convey.ShouldNotBeNil)
})
}
func TestDao_SearchFaceCheckRes(t *testing.T) {
convey.Convey("SearchFaceCheckRes", t, func() {
result, err := d.SearchFaceCheckRes(context.Background(), "2879cd5fb8518f7c6da75887994c1b2a7fe670bd.png")
convey.So(err, convey.ShouldBeNil)
convey.So(result, convey.ShouldNotBeNil)
})
}
func TestDao_SearchUserAuditLog(t *testing.T) {
convey.Convey("SearchUserAuditLog", t, func() {
result, err := d.SearchUserAuditLog(context.Background(), 1164)
convey.So(err, convey.ShouldBeNil)
convey.So(result, convey.ShouldNotBeNil)
})
}
func TestDao_SearchUserPropertyReview(t *testing.T) {
convey.Convey("SearchFaceCheckRes", t, func() {
etime := time.Now().Format("2006-01-02 15:04:05")
stime := time.Now().AddDate(0, 0, -26).Format("2006-01-02 15:04:05")
result, err := d.SearchUserPropertyReview(context.Background(), 0, []int{1}, []int{1, 2}, false, false, "", stime, etime, 1, 10)
convey.So(err, convey.ShouldBeNil)
convey.So(result, convey.ShouldNotBeNil)
})
}