Create & Init Project...
This commit is contained in:
22
app/service/main/passport-game/BUILD
Normal file
22
app/service/main/passport-game/BUILD
Normal file
@ -0,0 +1,22 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//app/service/main/passport-game/cmd:all-srcs",
|
||||
"//app/service/main/passport-game/conf:all-srcs",
|
||||
"//app/service/main/passport-game/dao:all-srcs",
|
||||
"//app/service/main/passport-game/http:all-srcs",
|
||||
"//app/service/main/passport-game/model:all-srcs",
|
||||
"//app/service/main/passport-game/service:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
67
app/service/main/passport-game/CHANGELOG.md
Normal file
67
app/service/main/passport-game/CHANGELOG.md
Normal file
@ -0,0 +1,67 @@
|
||||
## passport-game-service
|
||||
|
||||
#### Version 1.13.1
|
||||
> 1. 修复myinfo bug
|
||||
|
||||
#### Version 1.13.0
|
||||
> 1. 增加用户手机邮箱信息
|
||||
|
||||
#### Version 1.12.0
|
||||
> 1. 增加支持重置密码短信发送
|
||||
|
||||
#### Version 1.11.0
|
||||
> 1. 缓存来自 origin 的结果
|
||||
|
||||
#### Version 1.10.1
|
||||
> 1. 增加ut
|
||||
|
||||
#### Version 1.9.1
|
||||
> 1. add x-forward header
|
||||
|
||||
#### Version 1.9.0
|
||||
> 1. 增加regv3接口
|
||||
|
||||
#### Version 1.8.0
|
||||
> 1. add other region db
|
||||
> 2. update RemoteIP
|
||||
|
||||
#### Version 1.7.0
|
||||
> 1. bm && mv dir
|
||||
|
||||
#### Version 1.6.2
|
||||
> 1.renew token on origin in priority
|
||||
|
||||
#### Version 1.6.1
|
||||
> 1.fix password not matches when salt is empty
|
||||
|
||||
#### Version 1.6.0
|
||||
> 1.remove cold 30s when back to origin password error
|
||||
> 2.add info log when back to origin ok
|
||||
|
||||
#### Version 1.5.0
|
||||
> 1.use origin public and private key
|
||||
|
||||
#### Version 1.4.0
|
||||
> 1.generate new public key and private key instead of using origin's
|
||||
> 2.remove account table usage
|
||||
> 3.change perm, info model to pb
|
||||
> 4.add pb cache reading APIs
|
||||
> 5.reduce cache reading times of api myinfo and oauth
|
||||
> 6.add info API
|
||||
|
||||
#### Version 1.3.0
|
||||
> 1.move to kratos
|
||||
> 2.add oauth and renewToken dispatch
|
||||
|
||||
#### Version 1.2.1
|
||||
> 1.token proc bugfix: unmarshall `ctime` `mtime` error
|
||||
|
||||
#### Version 1.2.0
|
||||
> 1.token 消费优化
|
||||
|
||||
#### Version 1.1.0
|
||||
> 1.api login
|
||||
> 2.api get key
|
||||
|
||||
#### Version 1.0.0
|
||||
> 1.基础api
|
11
app/service/main/passport-game/CONTRIBUTORS.md
Normal file
11
app/service/main/passport-game/CONTRIBUTORS.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Owner
|
||||
wanghuan01
|
||||
zhoujiahui
|
||||
|
||||
# Author
|
||||
wanghuan01
|
||||
wutao
|
||||
gezhangyuan
|
||||
|
||||
# Reviewer
|
||||
wanghuan01
|
17
app/service/main/passport-game/OWNERS
Normal file
17
app/service/main/passport-game/OWNERS
Normal file
@ -0,0 +1,17 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- gezhangyuan
|
||||
- wanghuan01
|
||||
- wutao
|
||||
- zhoujiahui
|
||||
labels:
|
||||
- main
|
||||
- service
|
||||
- service/main/passport-game
|
||||
options:
|
||||
no_parent_owners: true
|
||||
reviewers:
|
||||
- gezhangyuan
|
||||
- wanghuan01
|
||||
- wutao
|
38
app/service/main/passport-game/README.md
Normal file
38
app/service/main/passport-game/README.md
Normal file
@ -0,0 +1,38 @@
|
||||
## passport-game-service
|
||||
|
||||
#### 项目简介
|
||||
> 1.游戏云账号服务
|
||||
|
||||
#### 编译环境
|
||||
> 请只用golang v1.8.x以上版本编译执行。
|
||||
|
||||
#### 依赖包
|
||||
> 1.公共包go-common
|
||||
|
||||
#### 特别说明
|
||||
> 1.model目录可能会被其他项目引用,请谨慎更改并通知各方。
|
||||
|
||||
#### 部署注意
|
||||
> 1.确定配置文件中 httpClient 节点中的 key 在 aso_apps 表中存在,且 issystem字段为 1。
|
||||
> 2.确定使用上述 key 访问源站 /api/login 接口返回正常(非 -1、-403、-105)。
|
||||
> 3.确定使用上述 key 访问源站 /api/login/oauth、/api/login/renewToken 接口返回正常(非 -1、-403)
|
||||
> 2.确定配置文件中 db.cloud 节点中所指向的数据库的 app 表包含了 identify-game-service 的 appkey。
|
||||
|
||||
#### 部署检查
|
||||
```
|
||||
ssh root@online-host
|
||||
# expected -629
|
||||
curl 'http://passport.bilibili.com/api/login?appkey=868fb9ea57619022&ts=1514374489&sign=12abbf6d77076cbb6627d4b8ecea1e43'
|
||||
# expected -101
|
||||
curl 'http://passport.bilibili.com/api/oauth?appkey=868fb9ea57619022&ts=1514374489&sign=12abbf6d77076cbb6627d4b8ecea1e43'
|
||||
# expected -101
|
||||
curl 'http://passport.bilibili.com/api/login/renewToken?appkey=868fb9ea57619022&ts=1514374489&sign=12abbf6d77076cbb6627d4b8ecea1e43'
|
||||
|
||||
# expected -101
|
||||
curl 'http://api.bilibili.co/x/internal/identify-game/oauth?appkey=868fb9ea57619022&ts=1514374489&sign=12abbf6d77076cbb6627d4b8ecea1e43'
|
||||
# expected -101
|
||||
curl 'http://api.bilibili.co/x/internal/identify-game/renewtoken?appkey=868fb9ea57619022&ts=1514374489&sign=12abbf6d77076cbb6627d4b8ecea1e43'
|
||||
```
|
||||
|
||||
#### 接入注意
|
||||
> 1.使用本服务,key 接口和 login 接口需要配套使用,如果用来加密密码的公钥与 key 接口返回的公钥不相同,会返回错误 -500。
|
41
app/service/main/passport-game/cmd/BUILD
Normal file
41
app/service/main/passport-game/cmd/BUILD
Normal file
@ -0,0 +1,41 @@
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_binary",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["main.go"],
|
||||
data = ["passport-game-service.toml"],
|
||||
importpath = "go-common/app/service/main/passport-game/cmd",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//app/service/main/passport-game/conf:go_default_library",
|
||||
"//app/service/main/passport-game/http:go_default_library",
|
||||
"//app/service/main/passport-game/service:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/trace:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "cmd",
|
||||
embed = [":go_default_library"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
48
app/service/main/passport-game/cmd/main.go
Normal file
48
app/service/main/passport-game/cmd/main.go
Normal file
@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"go-common/app/service/main/passport-game/conf"
|
||||
"go-common/app/service/main/passport-game/http"
|
||||
"go-common/app/service/main/passport-game/service"
|
||||
"go-common/library/log"
|
||||
"go-common/library/net/trace"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if err := conf.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Init(conf.Conf.Xlog)
|
||||
defer log.Close()
|
||||
trace.Init(conf.Conf.Tracer)
|
||||
defer trace.Close()
|
||||
// service init
|
||||
srv := service.New(conf.Conf)
|
||||
http.Init(conf.Conf, srv)
|
||||
// signal handler
|
||||
log.Info("passport-game-service start")
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
|
||||
for {
|
||||
s := <-c
|
||||
log.Info("passport-game-service get a signal %s", s.String())
|
||||
switch s {
|
||||
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
|
||||
srv.Close()
|
||||
time.Sleep(time.Second * 2)
|
||||
log.Info("passport-game-service exit")
|
||||
return
|
||||
case syscall.SIGHUP:
|
||||
// TODO reload
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
# This is a TOML document. Boom.
|
||||
|
||||
# 这个项目比较特殊,部署在云上的,需要保留一下配置
|
||||
proxy = false
|
||||
accountURI = "http://account.bilibili.co"
|
||||
passportURI = "http://passport.bilibili.com"
|
||||
|
||||
family = "passport-game-service"
|
||||
env = "qa"
|
||||
|
||||
[db.cloud]
|
||||
addr = "172.16.33.205:3306"
|
||||
dsn = "account:wx2U1MwXRyWEuURw@tcp(172.16.33.205:3306)/member_app1?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
active = 5
|
||||
idle = 2
|
||||
queryTimeout = "1s"
|
||||
execTimeout = "2s"
|
||||
tranTimeout = "2s"
|
||||
[db.cloud.breaker]
|
||||
window = "3s"
|
||||
sleep = "100ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
[db.otherRegion]
|
||||
addr = "172.16.33.205:3306"
|
||||
dsn = "account:wx2U1MwXRyWEuURw@tcp(172.16.33.205:3306)/member_app2?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
active = 5
|
||||
idle = 2
|
||||
queryTimeout = "1s"
|
||||
execTimeout = "2s"
|
||||
tranTimeout = "2s"
|
||||
[db.otherRegion.breaker]
|
||||
window = "3s"
|
||||
sleep = "100ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
|
||||
[memcache]
|
||||
name = "passport-game-service"
|
||||
proto = "tcp"
|
||||
addr = "172.16.33.54:21211"
|
||||
idle = 5
|
||||
active = 10
|
||||
dialTimeout = "1s"
|
||||
readTimeout = "1s"
|
||||
writeTimeout = "1s"
|
||||
idleTimeout = "10s"
|
||||
expire = "10h"
|
||||
|
||||
[httpClient]
|
||||
key = "868fb9ea57619022"
|
||||
secret = "test"
|
||||
dial = "5s"
|
||||
timeout = "10s"
|
||||
keepAlive = "6s"
|
||||
timer = 10
|
||||
[httpClient.breaker]
|
||||
window = "3s"
|
||||
sleep = "100ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
|
||||
[dispatcher]
|
||||
name = "t1"
|
||||
[dispatcher.oauth]
|
||||
"origin"="http://api.bilibili.co/x/internal/identify-game/oauth"
|
||||
"t1" = "http://api.bilibili.com/x/passport-game/oauth"
|
||||
"t2" = "http://t2-api.bilibili.com/x/passport-game/oauth"
|
||||
[dispatcher.renewToken]
|
||||
"origin"="http://api.bilibili.co/x/internal/identify-game/renewtoken"
|
||||
"t1" = "http://api.bilibili.com/x/passport-game/renewtoken"
|
||||
"t2" = "http://t2-api.bilibili.com/x/passport-game/renewtoken"
|
||||
|
||||
[[dispatcher.regionInfos]]
|
||||
region = "市北"
|
||||
tokenSuffix = ""
|
||||
|
||||
[[dispatcher.regionInfos]]
|
||||
region = "腾讯云1"
|
||||
tokenSuffix = "t1"
|
||||
|
||||
[[dispatcher.regionInfos]]
|
||||
region = "腾讯云2"
|
||||
tokenSuffix = "t2"
|
37
app/service/main/passport-game/conf/BUILD
Normal file
37
app/service/main/passport-game/conf/BUILD
Normal file
@ -0,0 +1,37 @@
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["conf.go"],
|
||||
importpath = "go-common/app/service/main/passport-game/conf",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/service/main/passport-game/model:go_default_library",
|
||||
"//library/cache/memcache:go_default_library",
|
||||
"//library/conf:go_default_library",
|
||||
"//library/database/sql:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/net/trace:go_default_library",
|
||||
"//library/time:go_default_library",
|
||||
"//vendor/github.com/BurntSushi/toml:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
119
app/service/main/passport-game/conf/conf.go
Normal file
119
app/service/main/passport-game/conf/conf.go
Normal file
@ -0,0 +1,119 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/conf"
|
||||
"go-common/library/database/sql"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/trace"
|
||||
"go-common/library/time"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
var (
|
||||
confPath string
|
||||
// Conf conf.
|
||||
Conf = &Config{}
|
||||
client *conf.Client
|
||||
)
|
||||
|
||||
// Config config.
|
||||
type Config struct {
|
||||
// Proxy if proxy
|
||||
Proxy bool
|
||||
// URIs
|
||||
AccountURI string
|
||||
PassportURI string
|
||||
// Xlog log
|
||||
Xlog *log.Config
|
||||
// Tracer tracer
|
||||
Tracer *trace.Config
|
||||
// DB db
|
||||
DB *DB
|
||||
// Memcache memcache
|
||||
Memcache *Memcache
|
||||
// HTTPClient http client
|
||||
HTTPClient *bm.ClientConfig
|
||||
// HTTP server config
|
||||
BM *bm.ServerConfig
|
||||
// Dispatcher dispatcher
|
||||
Dispatcher *Dispatcher
|
||||
}
|
||||
|
||||
// Dispatcher dispatcher.
|
||||
type Dispatcher struct {
|
||||
Name string
|
||||
Oauth map[string]string
|
||||
RenewToken map[string]string
|
||||
RegionInfos []*model.RegionInfo
|
||||
}
|
||||
|
||||
// DB db config.
|
||||
type DB struct {
|
||||
Cloud *sql.Config
|
||||
OtherRegion *sql.Config
|
||||
}
|
||||
|
||||
// Memcache general memcache config.
|
||||
type Memcache struct {
|
||||
*memcache.Config
|
||||
Expire time.Duration
|
||||
}
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&confPath, "conf", "", "default config path")
|
||||
}
|
||||
|
||||
// Init init config.
|
||||
func Init() (err error) {
|
||||
if confPath != "" {
|
||||
return local()
|
||||
}
|
||||
return remote()
|
||||
}
|
||||
|
||||
func local() (err error) {
|
||||
_, err = toml.DecodeFile(confPath, &Conf)
|
||||
return
|
||||
}
|
||||
|
||||
func remote() (err error) {
|
||||
if client, err = conf.New(); err != nil {
|
||||
return
|
||||
}
|
||||
if err = load(); err != nil {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
for range client.Event() {
|
||||
log.Info("config reload")
|
||||
if load() != nil {
|
||||
log.Error("config reload error (%v)", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
func load() (err error) {
|
||||
var (
|
||||
s string
|
||||
ok bool
|
||||
tmpConf *Config
|
||||
)
|
||||
if s, ok = client.Toml2(); !ok {
|
||||
return errors.New("load config center error")
|
||||
}
|
||||
|
||||
if _, err = toml.Decode(s, &tmpConf); err != nil {
|
||||
return errors.New("could not decode config")
|
||||
}
|
||||
*Conf = *tmpConf
|
||||
return
|
||||
}
|
62
app/service/main/passport-game/dao/BUILD
Normal file
62
app/service/main/passport-game/dao/BUILD
Normal file
@ -0,0 +1,62 @@
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"api.go",
|
||||
"cache.go",
|
||||
"dao.go",
|
||||
"mc.go",
|
||||
"mysql.go",
|
||||
],
|
||||
importpath = "go-common/app/service/main/passport-game/dao",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/service/main/passport-game/conf:go_default_library",
|
||||
"//app/service/main/passport-game/model:go_default_library",
|
||||
"//library/cache/memcache: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/metadata:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"api_test.go",
|
||||
"cache_test.go",
|
||||
"dao_test.go",
|
||||
"mc_test.go",
|
||||
"mysql_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
rundir = ".",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//app/service/main/passport-game/conf:go_default_library",
|
||||
"//app/service/main/passport-game/model:go_default_library",
|
||||
"//vendor/github.com/smartystreets/goconvey/convey: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"],
|
||||
)
|
396
app/service/main/passport-game/dao/api.go
Normal file
396
app/service/main/passport-game/dao/api.go
Normal file
@ -0,0 +1,396 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
"go-common/library/net/metadata"
|
||||
)
|
||||
|
||||
// MyInfo get info from api.
|
||||
func (d *Dao) MyInfo(c context.Context, accessKey string) (accountInfo *model.Info, err error) {
|
||||
params := url.Values{}
|
||||
params.Set("access_key", accessKey)
|
||||
params.Set("type", "json")
|
||||
var res struct {
|
||||
Code int `json:"code"`
|
||||
model.Info
|
||||
}
|
||||
if err = d.client.Get(c, d.myInfoURI, metadata.String(c, metadata.RemoteIP), params, &res); err != nil {
|
||||
log.Error("myInfo url(%s) error(%v)", d.myInfoURI+"?"+params.Encode(), err)
|
||||
return
|
||||
}
|
||||
if res.Code != 0 {
|
||||
err = ecode.Int(res.Code)
|
||||
log.Error("myInfo url(%s) error(%v)", d.myInfoURI+"?"+params.Encode(), err)
|
||||
return
|
||||
}
|
||||
accountInfo = &res.Info
|
||||
return
|
||||
}
|
||||
|
||||
// Oauth oauth via passport api.
|
||||
func (d *Dao) Oauth(c context.Context, uri, accessKey, from string) (token *model.Token, err error) {
|
||||
params := url.Values{}
|
||||
params.Set("access_key", accessKey)
|
||||
params.Set("from", from)
|
||||
var res struct {
|
||||
Code int `json:"code"`
|
||||
Token *struct {
|
||||
Mid string `json:"mid"`
|
||||
AppID int32 `json:"appid"`
|
||||
AccessToken string `json:"access_key"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UserID string `json:"userid"`
|
||||
Uname string `json:"uname"`
|
||||
Expires string `json:"expires"`
|
||||
Permission string `json:"permission"`
|
||||
} `json:"access_info,omitempty"`
|
||||
Data *model.Token `json:"data,omitempty"`
|
||||
}
|
||||
if err = d.client.Get(c, uri, metadata.String(c, metadata.RemoteIP), params, &res); err != nil {
|
||||
log.Error("model oauth url(%s) error(%v)", uri+"?"+params.Encode(), err)
|
||||
return
|
||||
}
|
||||
if res.Code != 0 {
|
||||
err = ecode.Int(res.Code)
|
||||
log.Error("model oauth url(%s) error(%v)", uri+"?"+params.Encode(), err)
|
||||
return
|
||||
}
|
||||
if res.Token != nil {
|
||||
t := res.Token
|
||||
var mid int64
|
||||
if mid, err = strconv.ParseInt(t.Mid, 10, 64); err != nil {
|
||||
log.Error("strconv.ParseInt(%s, 10, 64) error(%v)", t.Mid, err)
|
||||
return
|
||||
}
|
||||
var expires int64
|
||||
if expires, err = strconv.ParseInt(t.Expires, 10, 64); err != nil {
|
||||
log.Error("strconv.ParseInt(%s, 10, 64) error(%v)", t.Expires, err)
|
||||
return
|
||||
}
|
||||
token = &model.Token{
|
||||
Mid: mid,
|
||||
AppID: t.AppID,
|
||||
AccessToken: t.AccessToken,
|
||||
CreateAt: t.CreateAt,
|
||||
UserID: t.UserID,
|
||||
Uname: t.Uname,
|
||||
Expires: expires,
|
||||
Permission: t.Permission,
|
||||
}
|
||||
} else {
|
||||
token = res.Data
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Login login via model api.
|
||||
func (d *Dao) Login(c context.Context, query, cookie string) (loginToken *model.LoginToken, err error) {
|
||||
req, err := http.NewRequest("GET", d.loginURI+"?"+query, nil)
|
||||
if err != nil {
|
||||
log.Error("http.NewRequest(GET, %s) error(%v)", d.loginURI+"?"+query, err)
|
||||
return
|
||||
}
|
||||
req.Header.Set("Cookie", cookie)
|
||||
req.Header.Set("X-BACKEND-BILI-REAL-IP", metadata.String(c, metadata.RemoteIP))
|
||||
var res struct {
|
||||
Code int `json:"code"`
|
||||
Mid int64 `json:"mid"`
|
||||
AccessKey string `json:"access_key"`
|
||||
Expires int64 `json:"expires"`
|
||||
}
|
||||
if err = d.client.Do(c, req, &res); err != nil {
|
||||
log.Error("model login url(%s) error(%v)", d.loginURI+"?"+query, err)
|
||||
return
|
||||
}
|
||||
if res.Code != 0 {
|
||||
err = ecode.Int(res.Code)
|
||||
log.Error("model login url(%s) error(%v)", d.loginURI+"?"+query, err)
|
||||
return
|
||||
}
|
||||
loginToken = &model.LoginToken{
|
||||
Mid: res.Mid,
|
||||
AccessKey: res.AccessKey,
|
||||
Expires: res.Expires,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// LoginOrigin login via passport api.
|
||||
func (d *Dao) LoginOrigin(c context.Context, userid, rsaPwd string) (loginToken *model.LoginToken, err error) {
|
||||
params := url.Values{}
|
||||
params.Set("userid", userid)
|
||||
params.Set("pwd", rsaPwd)
|
||||
var res struct {
|
||||
Code int `json:"code"`
|
||||
Mid int64 `json:"mid"`
|
||||
AccessKey string `json:"access_key"`
|
||||
Expires int64 `json:"expires"`
|
||||
}
|
||||
if err = d.client.Get(c, d.loginURI, metadata.String(c, metadata.RemoteIP), params, &res); err != nil {
|
||||
log.Error("login url(%s) error(%v)", d.loginURI+"?"+params.Encode(), err)
|
||||
return
|
||||
}
|
||||
if res.Code != 0 {
|
||||
err = ecode.Int(res.Code)
|
||||
log.Error("login url(%s) error(%v)", d.loginURI+"?"+params.Encode(), err)
|
||||
return
|
||||
}
|
||||
|
||||
str, _ := json.Marshal(res)
|
||||
log.Info("login url(%s) res(%s)", d.loginURI+"?"+params.Encode(), str)
|
||||
|
||||
loginToken = &model.LoginToken{
|
||||
Mid: res.Mid,
|
||||
AccessKey: res.AccessKey,
|
||||
Expires: res.Expires,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// RSAKeyOrigin get rsa pub key and ts hash via passport api.
|
||||
func (d *Dao) RSAKeyOrigin(c context.Context) (key *model.RSAKey, err error) {
|
||||
var res struct {
|
||||
*model.RSAKey
|
||||
Code int `json:"code"`
|
||||
}
|
||||
params := url.Values{}
|
||||
if err = d.client.Get(c, d.getKeyURI, metadata.String(c, metadata.RemoteIP), params, &res); err != nil {
|
||||
log.Error("key url(%s) error(%v)", d.getKeyURI+"?"+params.Encode(), err)
|
||||
return
|
||||
}
|
||||
if res.Code != 0 {
|
||||
err = ecode.Int(res.Code)
|
||||
log.Error("key url(%s) error(%v)", d.getKeyURI+"?"+params.Encode(), err)
|
||||
return
|
||||
}
|
||||
key = res.RSAKey
|
||||
return
|
||||
}
|
||||
|
||||
// RenewToken renew token via passport api.
|
||||
func (d *Dao) RenewToken(c context.Context, uri, ak, from string) (renewToken *model.RenewToken, err error) {
|
||||
params := url.Values{}
|
||||
params.Set("access_key", ak)
|
||||
params.Set("from", from)
|
||||
var res struct {
|
||||
Code int `json:"code"`
|
||||
Expires int64 `json:"expires"`
|
||||
Data struct {
|
||||
Expires int64 `json:"expires"`
|
||||
}
|
||||
}
|
||||
if err = d.client.Get(c, uri, metadata.String(c, metadata.RemoteIP), params, &res); err != nil {
|
||||
log.Error("renewtoken url(%s) error(%v)", uri+"?"+params.Encode(), err)
|
||||
return
|
||||
}
|
||||
if res.Code != 0 {
|
||||
err = ecode.Int(res.Code)
|
||||
log.Error("renewtoken url(%s) error(%v)", uri+"?"+params.Encode(), err)
|
||||
return
|
||||
}
|
||||
expires := res.Expires
|
||||
if expires == 0 {
|
||||
expires = res.Data.Expires
|
||||
}
|
||||
renewToken = &model.RenewToken{
|
||||
Expires: expires,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// RegV3 RegV3
|
||||
func (d *Dao) RegV3(c context.Context, tdoRegV3 model.TdoRegV3) (regV3 *model.ResRegV3, err error) {
|
||||
p := url.Values{}
|
||||
p.Add("userpwd", tdoRegV3.Arg.Pwd)
|
||||
p.Add("userid", tdoRegV3.Arg.User)
|
||||
p.Add("captcha", tdoRegV3.Arg.Captcha)
|
||||
p.Add("ctoken", tdoRegV3.Arg.Ctoken)
|
||||
req, err := d.client.NewRequest(http.MethodPost, d.regV3URI, tdoRegV3.IP, p)
|
||||
if err != nil {
|
||||
log.Error("client.NewRequest(GET, %s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("X-Forwarded-For", tdoRegV3.IP)
|
||||
req.Header.Set("Cookie", tdoRegV3.Cookie)
|
||||
var response struct {
|
||||
Code int `json:"code"`
|
||||
Mid int `json:"mid"`
|
||||
}
|
||||
if err = d.client.Do(c, req, &response); err != nil {
|
||||
log.Error("client.Do(%s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
if response.Code != ecode.OK.Code() {
|
||||
log.Warn("regv3 url(%s) code(%d)", req.URL.String(), response.Code)
|
||||
err = ecode.Int(response.Code)
|
||||
return
|
||||
}
|
||||
regV3 = new(model.ResRegV3)
|
||||
regV3.Mid = response.Mid
|
||||
return
|
||||
}
|
||||
|
||||
// RegV2 RegV2
|
||||
func (d *Dao) RegV2(c context.Context, tdoRegV2 model.TdoRegV2) (regV2 *model.ResRegV2, err error) {
|
||||
p := url.Values{}
|
||||
p.Add("captcha", tdoRegV2.Arg.Captcha)
|
||||
p.Add("ctoken", tdoRegV2.Arg.Ctoken)
|
||||
req, err := d.client.NewRequest(http.MethodPost, d.regV2URI, tdoRegV2.IP, p)
|
||||
if err != nil {
|
||||
log.Error("client.NewRequest(GET, %s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("X-Forwarded-For", tdoRegV2.IP)
|
||||
req.Header.Set("Cookie", tdoRegV2.Cookie)
|
||||
var response struct {
|
||||
Code int `json:"code"`
|
||||
Mid int `json:"mid"`
|
||||
AccessKey string `json:"access_key"`
|
||||
}
|
||||
if err = d.client.Do(c, req, &response); err != nil {
|
||||
log.Error("client.Do(%s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
if response.Code != ecode.OK.Code() {
|
||||
log.Warn("reg v2 url(%s) code(%d)", req.URL.String(), response.Code)
|
||||
err = ecode.Int(response.Code)
|
||||
return
|
||||
}
|
||||
regV2 = new(model.ResRegV2)
|
||||
regV2.Mid = response.Mid
|
||||
regV2.AccessKey = response.AccessKey
|
||||
return
|
||||
}
|
||||
|
||||
// Reg Reg
|
||||
func (d *Dao) Reg(c context.Context, tdoReg model.TdoReg) (reg *model.ResReg, err error) {
|
||||
p := url.Values{}
|
||||
p.Add("userpwd", tdoReg.Arg.Userpwd)
|
||||
p.Add("user", tdoReg.Arg.User)
|
||||
p.Add("email", tdoReg.Arg.Email)
|
||||
|
||||
// new request
|
||||
req, err := d.client.NewRequest(http.MethodPost, d.regURI, tdoReg.IP, p)
|
||||
if err != nil {
|
||||
log.Error("client.NewRequest(GET, %s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("X-Forwarded-For", tdoReg.IP)
|
||||
req.Header.Set("Cookie", tdoReg.Cookie)
|
||||
var response struct {
|
||||
Code int `json:"code"`
|
||||
Mid int `json:"mid"`
|
||||
}
|
||||
if err = d.client.Do(c, req, &response); err != nil {
|
||||
log.Error("client.Do(%s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
if response.Code != ecode.OK.Code() {
|
||||
log.Warn("reg url(%s) code(%d)", req.URL.String(), response.Code)
|
||||
err = ecode.Int(response.Code)
|
||||
return
|
||||
}
|
||||
reg = new(model.ResReg)
|
||||
reg.Mid = response.Mid
|
||||
return
|
||||
}
|
||||
|
||||
// ByTel ByTel
|
||||
func (d *Dao) ByTel(c context.Context, tdoByTel model.TdoByTel) (byTel *model.ResByTel, err error) {
|
||||
|
||||
p := url.Values{}
|
||||
p.Add("userpwd", tdoByTel.Arg.Userpwd)
|
||||
p.Add("tel", tdoByTel.Arg.Tel)
|
||||
p.Add("captcha", tdoByTel.Arg.Captcha)
|
||||
p.Add("country_id", tdoByTel.Arg.CountryID)
|
||||
p.Add("uname", tdoByTel.Arg.Uname)
|
||||
|
||||
// new request
|
||||
req, err := d.client.NewRequest(http.MethodPost, d.byTelURI, tdoByTel.IP, p)
|
||||
if err != nil {
|
||||
log.Error("client.NewRequest(GET, %s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("X-Forwarded-For", tdoByTel.IP)
|
||||
req.Header.Set("Cookie", tdoByTel.Cookie)
|
||||
var response struct {
|
||||
Code int `json:"code"`
|
||||
Data struct {
|
||||
Mid int `json:"mid"`
|
||||
AccessKey string `json:"access_key"`
|
||||
}
|
||||
}
|
||||
|
||||
if err = d.client.Do(c, req, &response); err != nil {
|
||||
log.Error("client.Do(%s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
if response.Code != ecode.OK.Code() {
|
||||
log.Warn("byTel url(%s) code(%d)", req.URL.String(), response.Code)
|
||||
err = ecode.Int(response.Code)
|
||||
return
|
||||
}
|
||||
byTel = new(model.ResByTel)
|
||||
byTel.Mid = response.Data.Mid
|
||||
byTel.AccessKey = response.Data.AccessKey
|
||||
return
|
||||
}
|
||||
|
||||
// Captcha Captcha
|
||||
func (d *Dao) Captcha(c context.Context, ip string) (captchaData *model.CaptchaData, err error) {
|
||||
p := url.Values{}
|
||||
req, err := d.client.NewRequest(http.MethodGet, d.captchaURI, ip, p)
|
||||
if err != nil {
|
||||
log.Error("client.NewRequest(GET, %s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
resCaptcha := new(model.ResCaptcha)
|
||||
|
||||
req.Header.Set("X-Forwarded-For", ip)
|
||||
if err = d.client.Do(c, req, &resCaptcha); err != nil {
|
||||
log.Error("client.Do(%s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
|
||||
err = ecode.Int(resCaptcha.Code)
|
||||
captchaData = &resCaptcha.Data
|
||||
return
|
||||
}
|
||||
|
||||
// SendSms SendSms
|
||||
func (d *Dao) SendSms(c context.Context, tdoSendSms model.TdoSendSms) (err error) {
|
||||
p := url.Values{}
|
||||
p.Add("captcha", tdoSendSms.Arg.Captcha)
|
||||
p.Add("tel", tdoSendSms.Arg.Tel)
|
||||
p.Add("country_id", tdoSendSms.Arg.CountryID)
|
||||
p.Add("ctoken", tdoSendSms.Arg.Ctoken)
|
||||
p.Add("reset_pwd", strconv.FormatBool(tdoSendSms.Arg.ResetPwd))
|
||||
req, err := d.client.NewRequest(http.MethodGet, d.sendSmsURI, tdoSendSms.IP, p)
|
||||
if err != nil {
|
||||
log.Error("client.NewRequest(GET, %s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("X-Forwarded-For", tdoSendSms.IP)
|
||||
req.Header.Set("Cookie", tdoSendSms.Cookie)
|
||||
resCaptcha := new(model.ResCaptcha)
|
||||
if err = d.client.Do(c, req, &resCaptcha); err != nil {
|
||||
log.Error("client.Do(%s) error(%v)", req.URL.String(), err)
|
||||
return
|
||||
}
|
||||
|
||||
err = ecode.Int(resCaptcha.Code)
|
||||
return
|
||||
}
|
97
app/service/main/passport-game/dao/api_test.go
Normal file
97
app/service/main/passport-game/dao/api_test.go
Normal file
@ -0,0 +1,97 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestDaoMyInfo(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
accessKey = "123456"
|
||||
)
|
||||
convey.Convey("MyInfo", t, func(ctx convey.C) {
|
||||
accountInfo, err := d.MyInfo(c, accessKey)
|
||||
ctx.Convey("Then err should be nil.accountInfo should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldNotBeNil)
|
||||
ctx.So(accountInfo, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoOauth(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
uri = "https://wwww.baidu.com"
|
||||
accessKey = "123456"
|
||||
from = "baidu"
|
||||
)
|
||||
convey.Convey("Oauth", t, func(ctx convey.C) {
|
||||
token, err := d.Oauth(c, uri, accessKey, from)
|
||||
ctx.Convey("Then err should be nil.token should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldNotBeNil)
|
||||
ctx.So(token, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoLogin(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
query = "123"
|
||||
cookie = "123"
|
||||
)
|
||||
convey.Convey("Login", t, func(ctx convey.C) {
|
||||
loginToken, err := d.Login(c, query, cookie)
|
||||
ctx.Convey("Then err should be nil.loginToken should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldNotBeNil)
|
||||
ctx.So(loginToken, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoLoginOrigin(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
userid = "1"
|
||||
rsaPwd = "123456"
|
||||
)
|
||||
convey.Convey("LoginOrigin", t, func(ctx convey.C) {
|
||||
loginToken, err := d.LoginOrigin(c, userid, rsaPwd)
|
||||
ctx.Convey("Then err should be nil.loginToken should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldNotBeNil)
|
||||
ctx.So(loginToken, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoRSAKeyOrigin(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
)
|
||||
convey.Convey("RSAKeyOrigin", t, func(ctx convey.C) {
|
||||
key, err := d.RSAKeyOrigin(c)
|
||||
ctx.Convey("Then err should be nil.key should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(key, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoRenewToken(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
uri = "https://wwww.baidu.com"
|
||||
ak = "234"
|
||||
from = "234"
|
||||
)
|
||||
convey.Convey("RenewToken", t, func(ctx convey.C) {
|
||||
renewToken, err := d.RenewToken(c, uri, ak, from)
|
||||
ctx.Convey("Then err should be nil.renewToken should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldNotBeNil)
|
||||
ctx.So(renewToken, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
36
app/service/main/passport-game/dao/cache.go
Normal file
36
app/service/main/passport-game/dao/cache.go
Normal file
@ -0,0 +1,36 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
// TokenPBCache get token pb cache.
|
||||
func (d *Dao) TokenPBCache(c context.Context, key string) (res *model.Perm, err error) {
|
||||
if !strings.HasPrefix(key, _keyPrefixTokenPB) {
|
||||
err = fmt.Errorf("invalid cache key %s, key pattern is %s{token}", key, _keyPrefixInfoPB)
|
||||
return
|
||||
}
|
||||
token := key[len(_keyPrefixTokenPB):]
|
||||
return d.TokenCache(c, token)
|
||||
}
|
||||
|
||||
// InfoPBCache get info pb cache.
|
||||
func (d *Dao) InfoPBCache(c context.Context, key string) (res *model.Info, err error) {
|
||||
if !strings.HasPrefix(key, _keyPrefixInfoPB) {
|
||||
err = fmt.Errorf("invalid cache key %s, key pattern is %s{mid}", key, _keyPrefixInfoPB)
|
||||
return
|
||||
}
|
||||
midStr := key[len(_keyPrefixInfoPB):]
|
||||
mid, err := strconv.ParseInt(midStr, 10, 64)
|
||||
if err != nil {
|
||||
log.Error("strconv.ParseInt(%s, 10, 64) error(%v)", midStr, err)
|
||||
return
|
||||
}
|
||||
return d.InfoCache(c, mid)
|
||||
}
|
36
app/service/main/passport-game/dao/cache_test.go
Normal file
36
app/service/main/passport-game/dao/cache_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestDaoTokenPBCache(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
key = "123456"
|
||||
)
|
||||
convey.Convey("TokenPBCache", t, func(ctx convey.C) {
|
||||
res, err := d.TokenPBCache(c, key)
|
||||
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldNotBeNil)
|
||||
ctx.So(res, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoInfoPBCache(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
key = "123456"
|
||||
)
|
||||
convey.Convey("InfoPBCache", t, func(ctx convey.C) {
|
||||
res, err := d.InfoPBCache(c, key)
|
||||
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldNotBeNil)
|
||||
ctx.So(res, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
96
app/service/main/passport-game/dao/dao.go
Normal file
96
app/service/main/passport-game/dao/dao.go
Normal file
@ -0,0 +1,96 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go-common/app/service/main/passport-game/conf"
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/database/sql"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
// Dao dao
|
||||
type Dao struct {
|
||||
c *conf.Config
|
||||
getMemberStmt []*sql.Stmt
|
||||
cloudDB *sql.DB
|
||||
otherRegion *sql.DB
|
||||
mc *memcache.Pool
|
||||
mcExpire int32
|
||||
client *bm.Client
|
||||
myInfoURI string
|
||||
loginURI string
|
||||
getKeyURI string
|
||||
regV3URI string
|
||||
regV2URI string
|
||||
regURI string
|
||||
byTelURI string
|
||||
captchaURI string
|
||||
sendSmsURI string
|
||||
}
|
||||
|
||||
const (
|
||||
_myInfoURI = "/api/myinfo"
|
||||
_loginURI = "/api/login"
|
||||
_getKeyURI = "/api/login/get_key"
|
||||
_regV3URI = "/api/reg/regV3"
|
||||
_regV2URI = "/api/reg/regV2"
|
||||
_regURI = "/api/reg/reg"
|
||||
_byTelURI = "/api/reg/byTelGame"
|
||||
_captchaURI = "/bilicaptcha/token"
|
||||
_sendSmsURI = "/api/sms/sendCaptcha"
|
||||
)
|
||||
|
||||
// New dao
|
||||
func New(c *conf.Config) (d *Dao) {
|
||||
d = &Dao{
|
||||
c: c,
|
||||
cloudDB: sql.NewMySQL(c.DB.Cloud),
|
||||
otherRegion: sql.NewMySQL(c.DB.OtherRegion),
|
||||
mc: memcache.NewPool(c.Memcache.Config),
|
||||
mcExpire: int32(time.Duration(c.Memcache.Expire) / time.Second),
|
||||
client: bm.NewClient(c.HTTPClient),
|
||||
myInfoURI: c.AccountURI + _myInfoURI,
|
||||
loginURI: c.PassportURI + _loginURI,
|
||||
getKeyURI: c.PassportURI + _getKeyURI,
|
||||
regV3URI: c.PassportURI + _regV3URI,
|
||||
regV2URI: c.PassportURI + _regV2URI,
|
||||
regURI: c.PassportURI + _regURI,
|
||||
byTelURI: c.PassportURI + _byTelURI,
|
||||
captchaURI: c.PassportURI + _captchaURI,
|
||||
sendSmsURI: c.PassportURI + _sendSmsURI,
|
||||
}
|
||||
d.getMemberStmt = make([]*sql.Stmt, _memberShard)
|
||||
for i := 0; i < _memberShard; i++ {
|
||||
d.getMemberStmt[i] = d.cloudDB.Prepared(fmt.Sprintf(_getMemberInfoSQL, i))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Ping verify server is ok.
|
||||
func (d *Dao) Ping(c context.Context) (err error) {
|
||||
if err = d.cloudDB.Ping(c); err != nil {
|
||||
log.Info("dao.cloudDB.Ping() error(%v)", err)
|
||||
}
|
||||
if err = d.otherRegion.Ping(c); err != nil {
|
||||
log.Info("dao.otherRegion.Ping() error(%v)", err)
|
||||
}
|
||||
return d.pingMC(c)
|
||||
}
|
||||
|
||||
// Close close connections of mc, cloudDB.
|
||||
func (d *Dao) Close() (err error) {
|
||||
if d.cloudDB != nil {
|
||||
d.cloudDB.Close()
|
||||
}
|
||||
if d.otherRegion != nil {
|
||||
d.otherRegion.Close()
|
||||
}
|
||||
if d.mc != nil {
|
||||
d.mc.Close()
|
||||
}
|
||||
return
|
||||
}
|
34
app/service/main/passport-game/dao/dao_test.go
Normal file
34
app/service/main/passport-game/dao/dao_test.go
Normal file
@ -0,0 +1,34 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"go-common/app/service/main/passport-game/conf"
|
||||
)
|
||||
|
||||
var (
|
||||
d *Dao
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
if os.Getenv("DEPLOY_ENV") != "dev" {
|
||||
flag.Set("app_id", "main.account.passport-game-service")
|
||||
flag.Set("conf_token", "6461f64e47f084a2c9bbd505182dbe39")
|
||||
flag.Set("tree_id", "3791")
|
||||
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")
|
||||
}
|
||||
flag.Parse()
|
||||
if err := conf.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
d = New(conf.Conf)
|
||||
m.Run()
|
||||
os.Exit(0)
|
||||
}
|
243
app/service/main/passport-game/dao/mc.go
Normal file
243
app/service/main/passport-game/dao/mc.go
Normal file
@ -0,0 +1,243 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
const (
|
||||
_keyPrefixInfoPB = "pa2_"
|
||||
_keyPrefixTokenPB = "pt_"
|
||||
_keyPrefixOriginMissMatchFlag = "m_"
|
||||
_keyPrefixOriginToken = "pot_"
|
||||
|
||||
_missMatchFlagExpireSeconds = 30 // 30 seconds
|
||||
)
|
||||
|
||||
func keyInfoPB(mid int64) string {
|
||||
return _keyPrefixInfoPB + strconv.FormatInt(mid, 10)
|
||||
}
|
||||
|
||||
func keyTokenPB(accessToken string) string {
|
||||
return _keyPrefixTokenPB + accessToken
|
||||
}
|
||||
|
||||
func keyOriginToken(accessToken string) string {
|
||||
return _keyPrefixOriginToken + accessToken
|
||||
}
|
||||
|
||||
func keyOriginMissMatchFlag(identify string) string {
|
||||
return _keyPrefixOriginMissMatchFlag + identify
|
||||
}
|
||||
|
||||
// pingMC check connection success.
|
||||
func (d *Dao) pingMC(c context.Context) (err error) {
|
||||
item := &memcache.Item{
|
||||
Key: "ping",
|
||||
Value: []byte{1},
|
||||
Expiration: d.mcExpire,
|
||||
}
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
if err = conn.Set(item); err != nil {
|
||||
log.Error("conn.Set(%v) error(%v)", item, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SetInfoCache set info into cache.
|
||||
func (d *Dao) SetInfoCache(c context.Context, info *model.Info) (err error) {
|
||||
item := &memcache.Item{
|
||||
Key: keyInfoPB(info.Mid),
|
||||
Object: info,
|
||||
Flags: memcache.FlagProtobuf,
|
||||
Expiration: d.mcExpire,
|
||||
}
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
if err = conn.Set(item); err != nil {
|
||||
log.Error("conn.Set(%s) error(%v)", item.Key, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// InfoCache get info cache from cache.
|
||||
func (d *Dao) InfoCache(c context.Context, mid int64) (info *model.Info, err error) {
|
||||
key := keyInfoPB(mid)
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
var item *memcache.Item
|
||||
if item, err = conn.Get(key); err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
log.Error("conn.Get(%s) error(%v)", key, err)
|
||||
return
|
||||
}
|
||||
info = new(model.Info)
|
||||
if err = conn.Scan(item, info); err != nil {
|
||||
log.Error("conn.Scan(%s, %s) error(%v)", key, item.Value, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SetTokenCache set token into cache.
|
||||
func (d *Dao) SetTokenCache(c context.Context, token *model.Perm) (err error) {
|
||||
item := &memcache.Item{
|
||||
Key: keyTokenPB(token.AccessToken),
|
||||
Object: token,
|
||||
Flags: memcache.FlagProtobuf,
|
||||
Expiration: d.mcExpire,
|
||||
}
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
if err = conn.Set(item); err != nil {
|
||||
log.Error("conn.Set(%s) error(%v)", item.Key, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// TokenCache get token from cache.
|
||||
func (d *Dao) TokenCache(c context.Context, accessToken string) (token *model.Perm, err error) {
|
||||
key := keyTokenPB(accessToken)
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
item, err := conn.Get(key)
|
||||
if err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
log.Error("conn.Get(%s) error(%v)", key, err)
|
||||
return
|
||||
}
|
||||
token = new(model.Perm)
|
||||
if err = conn.Scan(item, token); err != nil {
|
||||
log.Error("conn.Scan(%s, %s) error(%v)", item.Key, item.Value, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DelTokenCache delete token from cache.
|
||||
func (d *Dao) DelTokenCache(c context.Context, accessToken string) (err error) {
|
||||
key := keyTokenPB(accessToken)
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
if err = conn.Delete(key); err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
log.Error("conn.Delete(%s) error(%v)", key, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SetOriginMissMatchFlagCache set origin miss match flag cache.
|
||||
func (d *Dao) SetOriginMissMatchFlagCache(c context.Context, identify string, flag []byte) (err error) {
|
||||
item := &memcache.Item{
|
||||
Key: keyOriginMissMatchFlag(identify),
|
||||
Value: flag,
|
||||
Expiration: _missMatchFlagExpireSeconds,
|
||||
}
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
if err = conn.Set(item); err != nil {
|
||||
log.Error("conn.Set(%s) error(%v)", item.Key, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OriginMissMatchFlagCache get origin miss match flag.
|
||||
func (d *Dao) OriginMissMatchFlagCache(c context.Context, identify string) (res []byte, err error) {
|
||||
key := keyOriginMissMatchFlag(identify)
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
var item *memcache.Item
|
||||
if item, err = conn.Get(key); err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
log.Error("conn.Get(%s) error(%v)", key, err)
|
||||
return
|
||||
}
|
||||
res = item.Value
|
||||
return
|
||||
}
|
||||
|
||||
// DelOriginMissMatchFlagCache delete origin miss match flag.
|
||||
func (d *Dao) DelOriginMissMatchFlagCache(c context.Context, identify string) (err error) {
|
||||
key := keyOriginMissMatchFlag(identify)
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
if err = conn.Delete(key); err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
log.Error("conn.Delete(%s) error(%v)", key, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SetOriginTokenCache set passport token into cache.
|
||||
func (d *Dao) SetOriginTokenCache(c context.Context, token *model.Token) (err error) {
|
||||
item := &memcache.Item{
|
||||
Key: keyOriginToken(token.AccessToken),
|
||||
Object: token,
|
||||
Flags: memcache.FlagJSON,
|
||||
Expiration: 60 + rand.Int31n(600),
|
||||
}
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
if err = conn.Set(item); err != nil {
|
||||
log.Error("conn.Set(%s) error(%v)", item.Key, err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OriginTokenCache set passport token into cache.
|
||||
func (d *Dao) OriginTokenCache(c context.Context, accessToken string) (token *model.Token, err error) {
|
||||
key := keyOriginToken(accessToken)
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
item, err := conn.Get(key)
|
||||
if err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
log.Error("conn.Get(%s) error(%v)", key, err)
|
||||
return
|
||||
}
|
||||
token = new(model.Token)
|
||||
if err = conn.Scan(item, token); err != nil {
|
||||
log.Error("conn.Scan(%s, %s) error(%v)", item.Key, item.Value, err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DelOriginTokenCache delete passport token from cache.
|
||||
func (d *Dao) DelOriginTokenCache(c context.Context, accessToken string) (err error) {
|
||||
key := keyOriginToken(accessToken)
|
||||
conn := d.mc.Get(c)
|
||||
defer conn.Close()
|
||||
if err = conn.Delete(key); err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
log.Error("conn.Delete(%s) error(%v)", key, err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
193
app/service/main/passport-game/dao/mc_test.go
Normal file
193
app/service/main/passport-game/dao/mc_test.go
Normal file
@ -0,0 +1,193 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"testing"
|
||||
|
||||
"github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestDaokeyInfoPB(t *testing.T) {
|
||||
var (
|
||||
mid = int64(12)
|
||||
)
|
||||
convey.Convey("keyInfoPB", t, func(ctx convey.C) {
|
||||
p1 := keyInfoPB(mid)
|
||||
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(p1, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaokeyTokenPB(t *testing.T) {
|
||||
var (
|
||||
accessToken = "123"
|
||||
)
|
||||
convey.Convey("keyTokenPB", t, func(ctx convey.C) {
|
||||
p1 := keyTokenPB(accessToken)
|
||||
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(p1, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaokeyOriginMissMatchFlag(t *testing.T) {
|
||||
var (
|
||||
identify = "123"
|
||||
)
|
||||
convey.Convey("keyOriginMissMatchFlag", t, func(ctx convey.C) {
|
||||
p1 := keyOriginMissMatchFlag(identify)
|
||||
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(p1, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaopingMC(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
)
|
||||
convey.Convey("pingMC", t, func(ctx convey.C) {
|
||||
err := d.pingMC(c)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoSetInfoCache(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
info = &model.Info{}
|
||||
)
|
||||
convey.Convey("SetInfoCache", t, func(ctx convey.C) {
|
||||
err := d.SetInfoCache(c, info)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoInfoCache(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
mid = int64(0)
|
||||
)
|
||||
convey.Convey("InfoCache", t, func(ctx convey.C) {
|
||||
info, err := d.InfoCache(c, mid)
|
||||
ctx.Convey("Then err should be nil.info should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(info, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoTokenCache(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
accessToken = "123456"
|
||||
token = &model.Perm{
|
||||
Mid: -1,
|
||||
AccessToken: accessToken,
|
||||
}
|
||||
)
|
||||
convey.Convey("TestDaoTokenCache", t, func(ctx convey.C) {
|
||||
err := d.SetTokenCache(c, token)
|
||||
ctx.Convey("SetTokenCache", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
|
||||
token, err := d.TokenCache(c, accessToken)
|
||||
ctx.Convey("TokenCache", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(token, convey.ShouldNotBeNil)
|
||||
})
|
||||
|
||||
err = d.DelTokenCache(c, accessToken)
|
||||
ctx.Convey("DelTokenCache", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
|
||||
token, err = d.TokenCache(c, accessToken)
|
||||
ctx.Convey("DeletedTokenCache", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(token, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoSetOriginMissMatchFlagCache(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
identify = "123456"
|
||||
flag = []byte("")
|
||||
)
|
||||
convey.Convey("SetOriginMissMatchFlagCache", t, func(ctx convey.C) {
|
||||
err := d.SetOriginMissMatchFlagCache(c, identify, flag)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoOriginMissMatchFlagCache(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
identify = "123456"
|
||||
)
|
||||
convey.Convey("OriginMissMatchFlagCache", t, func(ctx convey.C) {
|
||||
res, err := d.OriginMissMatchFlagCache(c, identify)
|
||||
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(res, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoDelOriginMissMatchFlagCache(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
identify = "123456"
|
||||
)
|
||||
convey.Convey("DelOriginMissMatchFlagCache", t, func(ctx convey.C) {
|
||||
err := d.DelOriginMissMatchFlagCache(c, identify)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoOriginTokenCache(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
accessToken = "123456"
|
||||
token = &model.Token{
|
||||
Mid: -1,
|
||||
AccessToken: accessToken,
|
||||
}
|
||||
)
|
||||
convey.Convey("TestDaoOriginTokenCache", t, func(ctx convey.C) {
|
||||
err := d.SetOriginTokenCache(c, token)
|
||||
ctx.Convey("SetOriginTokenCache", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
|
||||
token, err := d.OriginTokenCache(c, accessToken)
|
||||
ctx.Convey("OriginTokenCache", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(token, convey.ShouldNotBeNil)
|
||||
})
|
||||
|
||||
err = d.DelOriginTokenCache(c, accessToken)
|
||||
ctx.Convey("DelOriginTokenCache", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
|
||||
token, err = d.OriginTokenCache(c, accessToken)
|
||||
ctx.Convey("DeletedOriginTokenCache", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(token, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
147
app/service/main/passport-game/dao/mysql.go
Normal file
147
app/service/main/passport-game/dao/mysql.go
Normal file
@ -0,0 +1,147 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
xsql "go-common/library/database/sql"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
const (
|
||||
_memberShard = 30
|
||||
_getMemberInfoSQL = "SELECT mid,face FROM member_%02d WHERE mid=?"
|
||||
_getAppsSQL = "SELECT appid,appkey,app_secret FROM app"
|
||||
_addTokenSQL = "INSERT INTO app_perm (mid,appid,app_subid,access_token,create_at,expires) VALUES (?,?,?,?,?,?)"
|
||||
_updateTokenSQL = "UPDATE app_perm SET expires=? WHERE access_token=? AND expires<?"
|
||||
_getTokenSQL = "SELECT mid,appid,app_subid,access_token,create_at,expires FROM app_perm WHERE access_token=?"
|
||||
_getAsoAccountSQL = "SELECT mid,userid,uname,pwd,salt,isleak FROM aso_account WHERE userid=? OR email=? OR tel=?"
|
||||
_getAccountInfoSQL = "SELECT mid,userid,uname,email,tel FROM aso_account WHERE mid=?"
|
||||
)
|
||||
|
||||
func hit(mid int64) int64 {
|
||||
return mid % _memberShard
|
||||
}
|
||||
|
||||
// MemberInfo get member info.
|
||||
func (d *Dao) MemberInfo(c context.Context, mid int64) (res *model.Info, err error) {
|
||||
var row = d.getMemberStmt[hit(mid)].QueryRow(c, mid)
|
||||
res = new(model.Info)
|
||||
if err = row.Scan(&res.Mid, &res.Face); err != nil {
|
||||
if err == xsql.ErrNoRows {
|
||||
res = nil
|
||||
err = nil
|
||||
} else {
|
||||
log.Error("row.Scan() error(%v)", err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Apps get all apps.
|
||||
func (d *Dao) Apps(c context.Context) (res []*model.App, err error) {
|
||||
var rows *xsql.Rows
|
||||
if rows, err = d.cloudDB.Query(c, _getAppsSQL); err != nil {
|
||||
log.Error("get apps, dao.cloudDB.Query(%s) error(%v)", _getAppsSQL, err)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
app := new(model.App)
|
||||
if err = rows.Scan(&app.AppID, &app.AppKey, &app.AppSecret); err != nil {
|
||||
log.Error("row.Scan() error(%v)", err)
|
||||
res = nil
|
||||
return
|
||||
}
|
||||
res = append(res, app)
|
||||
}
|
||||
err = rows.Err()
|
||||
return
|
||||
}
|
||||
|
||||
// AddToken add token.
|
||||
func (d *Dao) AddToken(c context.Context, t *model.Perm) (affected int64, err error) {
|
||||
var res sql.Result
|
||||
if res, err = d.cloudDB.Exec(c, _addTokenSQL, t.Mid, t.AppID, t.AppSubID, t.AccessToken, t.CreateAt, t.Expires); err != nil {
|
||||
log.Error("add token, dao.cloudDB.Exec(%d, %d, %d, %s, %d, %d) error(%v)", t.Mid, t.AppID, t.AppSubID, t.AccessToken, t.CreateAt, t.Expires, err)
|
||||
return
|
||||
}
|
||||
return res.RowsAffected()
|
||||
}
|
||||
|
||||
// UpdateToken update token.
|
||||
func (d *Dao) UpdateToken(c context.Context, t *model.Perm) (affected int64, err error) {
|
||||
var res sql.Result
|
||||
if res, err = d.cloudDB.Exec(c, _updateTokenSQL, t.Expires, t.AccessToken, t.Expires); err != nil {
|
||||
log.Error("update token, dao.cloudDB.Exec(%d, %s, %d) error(%v)", t.Expires, t.AccessToken, t.Expires, err)
|
||||
return
|
||||
}
|
||||
return res.RowsAffected()
|
||||
}
|
||||
|
||||
// Token get token.
|
||||
func (d *Dao) Token(c context.Context, accessToken string) (res *model.Perm, err error) {
|
||||
row := d.cloudDB.QueryRow(c, _getTokenSQL, accessToken)
|
||||
res = new(model.Perm)
|
||||
if err = row.Scan(&res.Mid, &res.AppID, &res.AppSubID, &res.AccessToken, &res.CreateAt, &res.Expires); err != nil {
|
||||
if err == xsql.ErrNoRows {
|
||||
res = nil
|
||||
err = nil
|
||||
} else {
|
||||
log.Error("row.Scan() error(%v)", err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AsoAccount get aso account.
|
||||
func (d *Dao) AsoAccount(c context.Context, identify, identifyHash string) (res []*model.AsoAccount, err error) {
|
||||
var rows *xsql.Rows
|
||||
if rows, err = d.cloudDB.Query(c, _getAsoAccountSQL, identify, identifyHash, identifyHash); err != nil {
|
||||
log.Error("get apps, dao.cloudDB.Query(%s) error(%v)", _getAsoAccountSQL, err)
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
aso := new(model.AsoAccount)
|
||||
if err = rows.Scan(&aso.Mid, &aso.UserID, &aso.Uname, &aso.Pwd, &aso.Salt, &aso.Isleak); err != nil {
|
||||
log.Error("row.Scan() error(%v)", err)
|
||||
res = nil
|
||||
return
|
||||
}
|
||||
res = append(res, aso)
|
||||
}
|
||||
err = rows.Err()
|
||||
return
|
||||
}
|
||||
|
||||
// AccountInfo get account info.
|
||||
func (d *Dao) AccountInfo(c context.Context, mid int64) (res *model.AsoAccount, err error) {
|
||||
row := d.cloudDB.QueryRow(c, _getAccountInfoSQL, mid)
|
||||
res = new(model.AsoAccount)
|
||||
if err = row.Scan(&res.Mid, &res.UserID, &res.Uname, &res.Email, &res.Tel); err != nil {
|
||||
if err == xsql.ErrNoRows {
|
||||
res = nil
|
||||
err = nil
|
||||
} else {
|
||||
log.Error("row.Scan() error(%v)", err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// TokenFromOtherRegion get token from otherRegion.
|
||||
func (d *Dao) TokenFromOtherRegion(c context.Context, accessToken string) (res *model.Perm, err error) {
|
||||
row := d.otherRegion.QueryRow(c, _getTokenSQL, accessToken)
|
||||
res = new(model.Perm)
|
||||
if err = row.Scan(&res.Mid, &res.AppID, &res.AppSubID, &res.AccessToken, &res.CreateAt, &res.Expires); err != nil {
|
||||
if err == xsql.ErrNoRows {
|
||||
res = nil
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
log.Error("row.Scan() error(%v)", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
133
app/service/main/passport-game/dao/mysql_test.go
Normal file
133
app/service/main/passport-game/dao/mysql_test.go
Normal file
@ -0,0 +1,133 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"testing"
|
||||
|
||||
"github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestDaohit(t *testing.T) {
|
||||
var (
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("hit", t, func(ctx convey.C) {
|
||||
p1 := hit(mid)
|
||||
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(p1, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoMemberInfo(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("MemberInfo", t, func(ctx convey.C) {
|
||||
res, err := d.MemberInfo(c, mid)
|
||||
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(res, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoApps(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
)
|
||||
convey.Convey("Apps", t, func(ctx convey.C) {
|
||||
res, err := d.Apps(c)
|
||||
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(res, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoAddToken(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
no = &model.Perm{}
|
||||
)
|
||||
convey.Convey("AddToken", t, func(ctx convey.C) {
|
||||
affected, err := d.AddToken(c, no)
|
||||
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldNotBeNil)
|
||||
ctx.So(affected, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoUpdateToken(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
no = &model.Perm{}
|
||||
)
|
||||
convey.Convey("UpdateToken", t, func(ctx convey.C) {
|
||||
affected, err := d.UpdateToken(c, no)
|
||||
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(affected, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoToken(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
accessToken = "123456"
|
||||
)
|
||||
convey.Convey("Token", t, func(ctx convey.C) {
|
||||
res, err := d.Token(c, accessToken)
|
||||
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(res, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoAsoAccount(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
identify = "123456"
|
||||
identifyHash = "654321"
|
||||
)
|
||||
convey.Convey("AsoAccount", t, func(ctx convey.C) {
|
||||
res, err := d.AsoAccount(c, identify, identifyHash)
|
||||
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(res, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoAccountInfo(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("AccountInfo", t, func(ctx convey.C) {
|
||||
res, err := d.AccountInfo(c, mid)
|
||||
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(res, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoTokenFromOtherRegion(t *testing.T) {
|
||||
var (
|
||||
c = context.TODO()
|
||||
accessToken = "123456"
|
||||
)
|
||||
convey.Convey("TokenFromOtherRegion", t, func(ctx convey.C) {
|
||||
res, err := d.TokenFromOtherRegion(c, accessToken)
|
||||
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(res, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
44
app/service/main/passport-game/http/BUILD
Normal file
44
app/service/main/passport-game/http/BUILD
Normal file
@ -0,0 +1,44 @@
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"account.go",
|
||||
"cache.go",
|
||||
"cloud.go",
|
||||
"http.go",
|
||||
"passport.go",
|
||||
"passport_login.go",
|
||||
"passport_reg.go",
|
||||
"sign.go",
|
||||
],
|
||||
importpath = "go-common/app/service/main/passport-game/http",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/service/main/passport-game/conf:go_default_library",
|
||||
"//app/service/main/passport-game/model:go_default_library",
|
||||
"//app/service/main/passport-game/service:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/net/metadata: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"],
|
||||
)
|
51
app/service/main/passport-game/http/account.go
Normal file
51
app/service/main/passport-game/http/account.go
Normal file
@ -0,0 +1,51 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func myInfo(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
params = c.Request.Form
|
||||
accessKey = params.Get("access_key")
|
||||
)
|
||||
if accessKey == "" {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
app, ok := c.Get("app")
|
||||
if !ok {
|
||||
c.JSON(nil, ecode.AppKeyInvalid)
|
||||
return
|
||||
}
|
||||
info, err := srv.MyInfo(c, app.(*model.App), accessKey)
|
||||
if err != nil {
|
||||
log.Error("service.MyInfo(%s) error(%v)", accessKey, err)
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(info, nil)
|
||||
}
|
||||
|
||||
func info(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
midStr = c.Request.Form.Get("mid")
|
||||
)
|
||||
if midStr == "" {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
mid, err := strconv.ParseInt(midStr, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
c.JSON(srv.Info(c, mid), nil)
|
||||
}
|
49
app/service/main/passport-game/http/cache.go
Normal file
49
app/service/main/passport-game/http/cache.go
Normal file
@ -0,0 +1,49 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func infoPBCache(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
key = c.Request.Form.Get("key")
|
||||
)
|
||||
if key == "" {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
info, err := srv.InfoPBCache(c, key)
|
||||
if err != nil {
|
||||
log.Error("service.InfoPBCache(%s) error(%v)", key, err)
|
||||
res := map[string]interface{}{}
|
||||
res["code"] = err
|
||||
res["message"] = err.Error()
|
||||
c.JSONMap(res, nil)
|
||||
return
|
||||
}
|
||||
c.JSON(info, nil)
|
||||
}
|
||||
|
||||
func tokenPBCache(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
key = c.Request.Form.Get("key")
|
||||
)
|
||||
if key == "" {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
info, err := srv.TokenPBCache(c, key)
|
||||
if err != nil {
|
||||
log.Error("service.TokenPBCache(%s) error(%v)", key, err)
|
||||
res := map[string]interface{}{}
|
||||
res["code"] = err
|
||||
res["message"] = err.Error()
|
||||
c.JSONMap(res, nil)
|
||||
return
|
||||
}
|
||||
c.JSON(info, nil)
|
||||
}
|
9
app/service/main/passport-game/http/cloud.go
Normal file
9
app/service/main/passport-game/http/cloud.go
Normal file
@ -0,0 +1,9 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func regions(c *blademaster.Context) {
|
||||
c.JSON(srv.Regions(c), nil)
|
||||
}
|
81
app/service/main/passport-game/http/http.go
Normal file
81
app/service/main/passport-game/http/http.go
Normal file
@ -0,0 +1,81 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go-common/app/service/main/passport-game/conf"
|
||||
"go-common/app/service/main/passport-game/service"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
var (
|
||||
srv *service.Service
|
||||
)
|
||||
|
||||
// Init init http sever instance.
|
||||
func Init(c *conf.Config, s *service.Service) {
|
||||
srv = s
|
||||
// init inner router
|
||||
engine := bm.DefaultServer(c.BM)
|
||||
initRouter(engine)
|
||||
// init inner server
|
||||
if err := engine.Start(); err != nil {
|
||||
log.Error("engine.Start error(%v)", err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// initRouter init inner router.
|
||||
func initRouter(e *bm.Engine) {
|
||||
// health check
|
||||
e.Ping(ping)
|
||||
e.Register(register)
|
||||
// new defined api lists
|
||||
g := e.Group("/x/passport-game")
|
||||
{
|
||||
g.GET("/oauth", verify, oauth)
|
||||
g.GET("/myinfo", verify, myInfo)
|
||||
g.GET("/info", verify, info)
|
||||
g.GET("/key", verify, getKeyProxy)
|
||||
g.GET("/login", verify, loginProxy)
|
||||
g.GET("/renewtoken", verify, renewToken)
|
||||
g.GET("/regions", verify, regions)
|
||||
g.POST("/reg/v3", verify, regV3)
|
||||
g.POST("/reg/v2", verify, regV2)
|
||||
g.POST("/reg", verify, reg)
|
||||
g.POST("/reg/byTel", verify, byTel)
|
||||
|
||||
g.GET("/captcha", verify, captcha)
|
||||
g.POST("/sendSms", verify, sendSms)
|
||||
}
|
||||
|
||||
inner := e.Group("/cache/pb")
|
||||
{
|
||||
inner.GET("/token", tokenPBCache)
|
||||
inner.GET("/info", infoPBCache)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func verify(c *bm.Context) {
|
||||
app, err := verifySign(c, srv)
|
||||
if err != nil {
|
||||
c.JSON(nil, err)
|
||||
c.Abort()
|
||||
}
|
||||
c.Set("app", app)
|
||||
}
|
||||
|
||||
// ping check server ok.
|
||||
func ping(c *bm.Context) {
|
||||
if err := srv.Ping(c); err != nil {
|
||||
log.Error("ping error(%v)", err)
|
||||
c.AbortWithStatus(http.StatusServiceUnavailable)
|
||||
}
|
||||
}
|
||||
|
||||
// register support discovery.
|
||||
func register(c *bm.Context) {
|
||||
c.JSON(map[string]struct{}{}, nil)
|
||||
}
|
81
app/service/main/passport-game/http/passport.go
Normal file
81
app/service/main/passport-game/http/passport.go
Normal file
@ -0,0 +1,81 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/app/service/main/passport-game/service"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func oauth(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
params = c.Request.Form
|
||||
accessKey = params.Get("access_key")
|
||||
from = params.Get("from")
|
||||
)
|
||||
if accessKey == "" {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
app, ok := c.Get("app")
|
||||
if !ok {
|
||||
c.JSON(nil, ecode.AppKeyInvalid)
|
||||
return
|
||||
}
|
||||
var token *model.Token
|
||||
if token, err = srv.Oauth(c, app.(*model.App), accessKey, from); err != nil {
|
||||
log.Error("service.Oauth(%s) error(%v)", accessKey, err)
|
||||
res := map[string]interface{}{}
|
||||
if err == service.ErrDispatcherError {
|
||||
res["message"] = err.Error()
|
||||
}
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(token, nil)
|
||||
}
|
||||
|
||||
func getKeyOrigin(c *bm.Context) {
|
||||
var err error
|
||||
var t *model.RSAKey
|
||||
if t, err = srv.RSAKeyOrigin(c); err != nil {
|
||||
log.Error("service.RSAKeyOrigin() error(%v)", err)
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(t, nil)
|
||||
}
|
||||
|
||||
func getKey(c *bm.Context) {
|
||||
c.JSON(srv.RSAKey(c), nil)
|
||||
}
|
||||
|
||||
func getKeyProxy(c *bm.Context) {
|
||||
if srv.Proxy(c) {
|
||||
getKeyOrigin(c)
|
||||
return
|
||||
}
|
||||
getKey(c)
|
||||
}
|
||||
|
||||
func renewToken(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
params = c.Request.Form
|
||||
accessKey = params.Get("access_key")
|
||||
from = params.Get("from")
|
||||
)
|
||||
var r *model.RenewToken
|
||||
if r, err = srv.RenewToken(c, accessKey, from); err != nil {
|
||||
log.Error("service.RenewToken() error(%v)", err)
|
||||
res := map[string]interface{}{}
|
||||
if err == service.ErrDispatcherError {
|
||||
res["message"] = err.Error()
|
||||
}
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(r, nil)
|
||||
}
|
62
app/service/main/passport-game/http/passport_login.go
Normal file
62
app/service/main/passport-game/http/passport_login.go
Normal file
@ -0,0 +1,62 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func loginOrigin(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
t *model.LoginToken
|
||||
params = c.Request.Form
|
||||
cookie = c.Request.Header.Get("Cookie")
|
||||
)
|
||||
if t, err = srv.LoginOrigin(c, params.Encode(), cookie); err != nil {
|
||||
log.Error("service.LoginOrigin(%s, %s) error(%v)", params.Encode(), cookie, err)
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(t, nil)
|
||||
}
|
||||
|
||||
func login(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
subid = int64(0)
|
||||
params = c.Request.Form
|
||||
subidStr = params.Get("subid")
|
||||
userid = params.Get("userid")
|
||||
rsaPwd = params.Get("pwd")
|
||||
)
|
||||
if subidStr != "" {
|
||||
if subid, err = strconv.ParseInt(subidStr, 10, 32); err != nil {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
}
|
||||
app, ok := c.Get("app")
|
||||
if !ok {
|
||||
c.JSON(nil, ecode.AppKeyInvalid)
|
||||
return
|
||||
}
|
||||
t, err := srv.Login(c, app.(*model.App), int32(subid), userid, rsaPwd)
|
||||
if err != nil {
|
||||
log.Error("service.Login() error(%v)", err)
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(t, err)
|
||||
}
|
||||
|
||||
func loginProxy(c *bm.Context) {
|
||||
if srv.Proxy(c) {
|
||||
loginOrigin(c)
|
||||
return
|
||||
}
|
||||
login(c)
|
||||
}
|
67
app/service/main/passport-game/http/passport_reg.go
Normal file
67
app/service/main/passport-game/http/passport_reg.go
Normal file
@ -0,0 +1,67 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/metadata"
|
||||
)
|
||||
|
||||
func regV3(c *bm.Context) {
|
||||
var argRegV3 = new(model.ArgRegV3)
|
||||
err := c.Bind(argRegV3)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var cookie = c.Request.Header.Get("Cookie")
|
||||
c.JSON(srv.RegV3(c, model.TdoRegV3{Arg: *argRegV3, IP: metadata.String(c, metadata.RemoteIP), Cookie: cookie}))
|
||||
}
|
||||
|
||||
func regV2(c *bm.Context) {
|
||||
var argRegV2 = new(model.ArgRegV2)
|
||||
err := c.Bind(argRegV2)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var cookie = c.Request.Header.Get("Cookie")
|
||||
c.JSON(srv.RegV2(c, model.TdoRegV2{Arg: *argRegV2, IP: metadata.String(c, metadata.RemoteIP), Cookie: cookie}))
|
||||
}
|
||||
|
||||
func reg(c *bm.Context) {
|
||||
var argReg = new(model.ArgReg)
|
||||
err := c.Bind(argReg)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var cookie = c.Request.Header.Get("Cookie")
|
||||
c.JSON(srv.Reg(c, model.TdoReg{Arg: *argReg, IP: metadata.String(c, metadata.RemoteIP), Cookie: cookie}))
|
||||
}
|
||||
|
||||
func byTel(c *bm.Context) {
|
||||
var argByTel = new(model.ArgByTel)
|
||||
err := c.Bind(argByTel)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var cookie = c.Request.Header.Get("Cookie")
|
||||
c.JSON(srv.ByTel(c, model.TdoByTel{Arg: *argByTel, IP: metadata.String(c, metadata.RemoteIP), Cookie: cookie}))
|
||||
}
|
||||
|
||||
func captcha(c *bm.Context) {
|
||||
c.JSON(srv.Captcha(c, metadata.String(c, metadata.RemoteIP)))
|
||||
}
|
||||
|
||||
func sendSms(c *bm.Context) {
|
||||
var sendSmsp = new(model.SendSms)
|
||||
berr := c.Bind(sendSmsp)
|
||||
if berr != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var cookie = c.Request.Header.Get("Cookie")
|
||||
err := srv.SendSms(c, model.TdoSendSms{Arg: *sendSmsp, IP: metadata.String(c, metadata.RemoteIP), Cookie: cookie})
|
||||
c.JSON(nil, err)
|
||||
}
|
88
app/service/main/passport-game/http/sign.go
Normal file
88
app/service/main/passport-game/http/sign.go
Normal file
@ -0,0 +1,88 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/app/service/main/passport-game/service"
|
||||
"go-common/library/ecode"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
// VerifySign verify sign.
|
||||
func verifySign(c *bm.Context, s *service.Service) (res *model.App, err error) {
|
||||
var (
|
||||
r = c.Request
|
||||
query = r.Form
|
||||
)
|
||||
if r.Method == "POST" {
|
||||
// Give priority to sign in url query, otherwise check sign in post form.
|
||||
p := c.Request.URL.Query()
|
||||
if p.Get("sign") != "" {
|
||||
query = p
|
||||
}
|
||||
}
|
||||
if query.Get("ts") == "" {
|
||||
err = ecode.RequestErr
|
||||
return
|
||||
}
|
||||
appKey := query.Get("appkey")
|
||||
if appKey == "" {
|
||||
err = ecode.RequestErr
|
||||
return
|
||||
}
|
||||
app, ok := s.APP(appKey)
|
||||
if !ok {
|
||||
err = ecode.AppKeyInvalid
|
||||
return
|
||||
}
|
||||
secret := app.AppSecret
|
||||
tmp := encodeQuery(query)
|
||||
if strings.IndexByte(tmp, '+') > -1 {
|
||||
tmp = strings.Replace(tmp, "+", "%20", -1)
|
||||
}
|
||||
mh := md5.Sum([]byte(strings.ToLower(tmp) + secret))
|
||||
sign := query.Get("sign")
|
||||
if hex.EncodeToString(mh[:]) != sign {
|
||||
mh1 := md5.Sum([]byte(tmp + secret))
|
||||
if hex.EncodeToString(mh1[:]) != sign {
|
||||
err = ecode.SignCheckErr
|
||||
}
|
||||
}
|
||||
res = app
|
||||
return
|
||||
}
|
||||
|
||||
// encodeQuery encodes the values into ``URL encoded'' form ("bar=baz&foo=quux") sorted by key.
|
||||
// NOTE: sign ignored!!!
|
||||
func encodeQuery(v url.Values) string {
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
keys := make([]string, 0, len(v))
|
||||
for k := range v {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
if k == "sign" {
|
||||
continue
|
||||
}
|
||||
vs := v[k]
|
||||
prefix := url.QueryEscape(k) + "="
|
||||
for _, v := range vs {
|
||||
if buf.Len() > 0 {
|
||||
buf.WriteByte('&')
|
||||
}
|
||||
buf.WriteString(prefix)
|
||||
buf.WriteString(url.QueryEscape(v))
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
58
app/service/main/passport-game/model/BUILD
Normal file
58
app/service/main/passport-game/model/BUILD
Normal file
@ -0,0 +1,58 @@
|
||||
load(
|
||||
"@io_bazel_rules_go//proto:def.bzl",
|
||||
"go_proto_library",
|
||||
)
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"cloud.go",
|
||||
"model.go",
|
||||
"open.go",
|
||||
],
|
||||
embed = [":model_go_proto"],
|
||||
importpath = "go-common/app/service/main/passport-game/model",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//library/time:go_default_library",
|
||||
"@com_github_gogo_protobuf//gogoproto:go_default_library",
|
||||
"@com_github_golang_protobuf//proto: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"],
|
||||
)
|
||||
|
||||
proto_library(
|
||||
name = "model_proto",
|
||||
srcs = ["model.proto"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
|
||||
)
|
||||
|
||||
go_proto_library(
|
||||
name = "model_go_proto",
|
||||
compilers = ["@io_bazel_rules_go//proto:gogofast_proto"],
|
||||
importpath = "go-common/app/service/main/passport-game/model",
|
||||
proto = ":model_proto",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@com_github_gogo_protobuf//gogoproto:go_default_library"],
|
||||
)
|
7
app/service/main/passport-game/model/cloud.go
Normal file
7
app/service/main/passport-game/model/cloud.go
Normal file
@ -0,0 +1,7 @@
|
||||
package model
|
||||
|
||||
// RegionInfo region item.
|
||||
type RegionInfo struct {
|
||||
Region string `json:"region"`
|
||||
TokenSuffix string `json:"token_suffix"`
|
||||
}
|
212
app/service/main/passport-game/model/model.go
Normal file
212
app/service/main/passport-game/model/model.go
Normal file
@ -0,0 +1,212 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
xtime "go-common/library/time"
|
||||
)
|
||||
|
||||
const (
|
||||
// EmptyFace empty face
|
||||
EmptyFace = "http://static.hdslb.com/images/member/noface.gif"
|
||||
|
||||
_cloudSalt = "bi_clould_tencent_01"
|
||||
_leak = 1
|
||||
)
|
||||
|
||||
// FullFace account full face.
|
||||
func (m *Info) FullFace() string {
|
||||
if m.Face == "" {
|
||||
return EmptyFace
|
||||
}
|
||||
return fmt.Sprintf("http://i%d.hdslb.com%s", m.Mid%3, m.Face)
|
||||
}
|
||||
|
||||
// Token token resp.
|
||||
type Token struct {
|
||||
Mid int64 `json:"mid"`
|
||||
AppID int32 `json:"appid"`
|
||||
AccessToken string `json:"access_key"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UserID string `json:"userid"`
|
||||
Uname string `json:"uname"`
|
||||
Expires int64 `json:"expires"`
|
||||
Permission string `json:"permission"`
|
||||
}
|
||||
|
||||
// LoginToken login token.
|
||||
type LoginToken struct {
|
||||
Mid int64 `json:"mid"`
|
||||
AccessKey string `json:"access_key"`
|
||||
Expires int64 `json:"expires"`
|
||||
}
|
||||
|
||||
// RSAKey rsa key.
|
||||
type RSAKey struct {
|
||||
Hash string `json:"hash"`
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
// RenewToken renew token resp.
|
||||
type RenewToken struct {
|
||||
Expires int64 `json:"expires"`
|
||||
}
|
||||
|
||||
// AsoAccount aso account.
|
||||
type AsoAccount struct {
|
||||
Mid int64 `json:"mid"`
|
||||
UserID string `json:"userid"`
|
||||
Uname string `json:"uname"`
|
||||
Pwd string `json:"pwd"`
|
||||
Salt string `json:"salt"`
|
||||
Email *string `json:"email"`
|
||||
Tel *string `json:"tel"`
|
||||
CountryID int64 `json:"country_id"`
|
||||
MobileVerified int8 `json:"mobile_verified"`
|
||||
Isleak int8 `json:"isleak"`
|
||||
Ctime xtime.Time `json:"-"`
|
||||
Mtime xtime.Time `json:"-"`
|
||||
}
|
||||
|
||||
// ResRegV3 ResRegV3
|
||||
type ResRegV3 struct {
|
||||
Mid int `json:"mid"`
|
||||
}
|
||||
|
||||
// ResRegV2 ResRegV2
|
||||
type ResRegV2 struct {
|
||||
Mid int `json:"mid"`
|
||||
AccessKey string `json:"accessKey"`
|
||||
}
|
||||
|
||||
// ResReg ResReg
|
||||
type ResReg struct {
|
||||
Mid int `json:"mid"`
|
||||
}
|
||||
|
||||
// ResByTel ResByTel
|
||||
type ResByTel struct {
|
||||
Mid int `json:"mid"`
|
||||
AccessKey string `json:"accessKey"`
|
||||
}
|
||||
|
||||
// ResCaptcha ResCaptcha
|
||||
type ResCaptcha struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data CaptchaData `json:"data"`
|
||||
}
|
||||
|
||||
// CaptchaData CaptchaData
|
||||
type CaptchaData struct {
|
||||
Token string `json:"token"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// ArgRegV3 ArgRegV3
|
||||
type ArgRegV3 struct {
|
||||
User string `form:"user" validate:"required"`
|
||||
Pwd string `form:"pwd" validate:"required"`
|
||||
Captcha string `form:"captcha"`
|
||||
Ctoken string `form:"ctoken"`
|
||||
}
|
||||
|
||||
// ArgRegV2 ArgRegV2
|
||||
type ArgRegV2 struct {
|
||||
Captcha string `form:"captcha"`
|
||||
Ctoken string `form:"ctoken"`
|
||||
}
|
||||
|
||||
// ArgReg ArgReg
|
||||
type ArgReg struct {
|
||||
Email string `form:"email" validate:"required"`
|
||||
Userpwd string `form:"pwd" validate:"required"`
|
||||
User string `form:"user" validate:"required"`
|
||||
}
|
||||
|
||||
// ArgByTel ArgByTel
|
||||
type ArgByTel struct {
|
||||
Tel string `form:"tel" validate:"required"`
|
||||
Uname string `form:"user" validate:"required"`
|
||||
Userpwd string `form:"pwd" validate:"required"`
|
||||
CountryID string `form:"country_id" validate:"required"`
|
||||
Captcha string `form:"captcha" validate:"required"`
|
||||
}
|
||||
|
||||
// SendSms SendSms
|
||||
type SendSms struct {
|
||||
Tel string `form:"tel" validate:"required"`
|
||||
CountryID string `form:"country_id" validate:"required"`
|
||||
Captcha string `form:"captcha" `
|
||||
Ctoken string `form:"ctoken" `
|
||||
ResetPwd bool `form:"reset_pwd" `
|
||||
}
|
||||
|
||||
// TdoRegV3 TdoRegV3
|
||||
type TdoRegV3 struct {
|
||||
Arg ArgRegV3
|
||||
Cookie string
|
||||
IP string
|
||||
}
|
||||
|
||||
// TdoRegV2 TdoRegV2
|
||||
type TdoRegV2 struct {
|
||||
Arg ArgRegV2
|
||||
Cookie string
|
||||
IP string
|
||||
}
|
||||
|
||||
// TdoReg TdoReg
|
||||
type TdoReg struct {
|
||||
Arg ArgReg
|
||||
Cookie string
|
||||
IP string
|
||||
}
|
||||
|
||||
// TdoByTel TdoByTel
|
||||
type TdoByTel struct {
|
||||
Arg ArgByTel
|
||||
Cookie string
|
||||
IP string
|
||||
}
|
||||
|
||||
// TdoSendSms TdoSendSms
|
||||
type TdoSendSms struct {
|
||||
Arg SendSms
|
||||
Cookie string
|
||||
IP string
|
||||
}
|
||||
|
||||
// Leak leak.
|
||||
func (a *AsoAccount) Leak() bool {
|
||||
return a.Isleak == _leak
|
||||
}
|
||||
|
||||
// DefaultHash hash a plain text using default salt.
|
||||
func DefaultHash(plaintext string) string {
|
||||
return doHash(plaintext, _cloudSalt)
|
||||
}
|
||||
|
||||
func doHash(plaintext, salt string) string {
|
||||
if plaintext == "" {
|
||||
return ""
|
||||
}
|
||||
hash := md5.New()
|
||||
hash.Write([]byte(plaintext))
|
||||
hash.Write([]byte(salt))
|
||||
md := hash.Sum(nil)
|
||||
return hex.EncodeToString(md)
|
||||
}
|
||||
|
||||
// DefaultUserID get default user id.
|
||||
func DefaultUserID(mid int64) string {
|
||||
return "用户" + strconv.FormatInt(mid, 10)
|
||||
}
|
||||
|
||||
// DefaultUname get default uname.
|
||||
func DefaultUname(mid int64) string {
|
||||
return "用户" + strconv.FormatInt(mid, 10)
|
||||
}
|
888
app/service/main/passport-game/model/model.pb.go
Normal file
888
app/service/main/passport-game/model/model.pb.go
Normal file
@ -0,0 +1,888 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: model.proto
|
||||
|
||||
/*
|
||||
Package model is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
model.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Info
|
||||
Perm
|
||||
*/
|
||||
package model
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Info account info.
|
||||
type Info struct {
|
||||
Mid int64 `protobuf:"varint,1,opt,name=Mid,proto3" json:"mid"`
|
||||
UserID string `protobuf:"bytes,2,opt,name=UserID,proto3" json:"userid"`
|
||||
Uname string `protobuf:"bytes,3,opt,name=Uname,proto3" json:"uname"`
|
||||
Face string `protobuf:"bytes,4,opt,name=Face,proto3" json:"face"`
|
||||
HasEmail bool `protobuf:"varint,5,opt,name=HasEmail,proto3" json:"has_email"`
|
||||
HasTel bool `protobuf:"varint,6,opt,name=HasTel,proto3" json:"has_tel"`
|
||||
}
|
||||
|
||||
func (m *Info) Reset() { *m = Info{} }
|
||||
func (m *Info) String() string { return proto.CompactTextString(m) }
|
||||
func (*Info) ProtoMessage() {}
|
||||
func (*Info) Descriptor() ([]byte, []int) { return fileDescriptorModel, []int{0} }
|
||||
|
||||
func (m *Info) GetMid() int64 {
|
||||
if m != nil {
|
||||
return m.Mid
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Info) GetUserID() string {
|
||||
if m != nil {
|
||||
return m.UserID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Info) GetUname() string {
|
||||
if m != nil {
|
||||
return m.Uname
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Info) GetFace() string {
|
||||
if m != nil {
|
||||
return m.Face
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Info) GetHasEmail() bool {
|
||||
if m != nil {
|
||||
return m.HasEmail
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Info) GetHasTel() bool {
|
||||
if m != nil {
|
||||
return m.HasTel
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Perm token.
|
||||
type Perm struct {
|
||||
Mid int64 `protobuf:"varint,1,opt,name=Mid,proto3" json:"mid"`
|
||||
AppID int32 `protobuf:"varint,2,opt,name=AppID,proto3" json:"appid"`
|
||||
AppSubID int32 `protobuf:"varint,3,opt,name=AppSubID,proto3" json:"app_subid"`
|
||||
AccessToken string `protobuf:"bytes,4,opt,name=AccessToken,proto3" json:"access_token"`
|
||||
RefreshToken string `protobuf:"bytes,5,opt,name=RefreshToken,proto3" json:"refresh_token"`
|
||||
CreateAt int64 `protobuf:"varint,6,opt,name=CreateAt,proto3" json:"create_at"`
|
||||
Expires int64 `protobuf:"varint,7,opt,name=Expires,proto3" json:"expires"`
|
||||
}
|
||||
|
||||
func (m *Perm) Reset() { *m = Perm{} }
|
||||
func (m *Perm) String() string { return proto.CompactTextString(m) }
|
||||
func (*Perm) ProtoMessage() {}
|
||||
func (*Perm) Descriptor() ([]byte, []int) { return fileDescriptorModel, []int{1} }
|
||||
|
||||
func (m *Perm) GetMid() int64 {
|
||||
if m != nil {
|
||||
return m.Mid
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Perm) GetAppID() int32 {
|
||||
if m != nil {
|
||||
return m.AppID
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Perm) GetAppSubID() int32 {
|
||||
if m != nil {
|
||||
return m.AppSubID
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Perm) GetAccessToken() string {
|
||||
if m != nil {
|
||||
return m.AccessToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Perm) GetRefreshToken() string {
|
||||
if m != nil {
|
||||
return m.RefreshToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Perm) GetCreateAt() int64 {
|
||||
if m != nil {
|
||||
return m.CreateAt
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Perm) GetExpires() int64 {
|
||||
if m != nil {
|
||||
return m.Expires
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Info)(nil), "model.Info")
|
||||
proto.RegisterType((*Perm)(nil), "model.Perm")
|
||||
}
|
||||
func (m *Info) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Info) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Mid != 0 {
|
||||
dAtA[i] = 0x8
|
||||
i++
|
||||
i = encodeVarintModel(dAtA, i, uint64(m.Mid))
|
||||
}
|
||||
if len(m.UserID) > 0 {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintModel(dAtA, i, uint64(len(m.UserID)))
|
||||
i += copy(dAtA[i:], m.UserID)
|
||||
}
|
||||
if len(m.Uname) > 0 {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintModel(dAtA, i, uint64(len(m.Uname)))
|
||||
i += copy(dAtA[i:], m.Uname)
|
||||
}
|
||||
if len(m.Face) > 0 {
|
||||
dAtA[i] = 0x22
|
||||
i++
|
||||
i = encodeVarintModel(dAtA, i, uint64(len(m.Face)))
|
||||
i += copy(dAtA[i:], m.Face)
|
||||
}
|
||||
if m.HasEmail {
|
||||
dAtA[i] = 0x28
|
||||
i++
|
||||
if m.HasEmail {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i++
|
||||
}
|
||||
if m.HasTel {
|
||||
dAtA[i] = 0x30
|
||||
i++
|
||||
if m.HasTel {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i++
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *Perm) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Perm) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Mid != 0 {
|
||||
dAtA[i] = 0x8
|
||||
i++
|
||||
i = encodeVarintModel(dAtA, i, uint64(m.Mid))
|
||||
}
|
||||
if m.AppID != 0 {
|
||||
dAtA[i] = 0x10
|
||||
i++
|
||||
i = encodeVarintModel(dAtA, i, uint64(m.AppID))
|
||||
}
|
||||
if m.AppSubID != 0 {
|
||||
dAtA[i] = 0x18
|
||||
i++
|
||||
i = encodeVarintModel(dAtA, i, uint64(m.AppSubID))
|
||||
}
|
||||
if len(m.AccessToken) > 0 {
|
||||
dAtA[i] = 0x22
|
||||
i++
|
||||
i = encodeVarintModel(dAtA, i, uint64(len(m.AccessToken)))
|
||||
i += copy(dAtA[i:], m.AccessToken)
|
||||
}
|
||||
if len(m.RefreshToken) > 0 {
|
||||
dAtA[i] = 0x2a
|
||||
i++
|
||||
i = encodeVarintModel(dAtA, i, uint64(len(m.RefreshToken)))
|
||||
i += copy(dAtA[i:], m.RefreshToken)
|
||||
}
|
||||
if m.CreateAt != 0 {
|
||||
dAtA[i] = 0x30
|
||||
i++
|
||||
i = encodeVarintModel(dAtA, i, uint64(m.CreateAt))
|
||||
}
|
||||
if m.Expires != 0 {
|
||||
dAtA[i] = 0x38
|
||||
i++
|
||||
i = encodeVarintModel(dAtA, i, uint64(m.Expires))
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeVarintModel(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *Info) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Mid != 0 {
|
||||
n += 1 + sovModel(uint64(m.Mid))
|
||||
}
|
||||
l = len(m.UserID)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovModel(uint64(l))
|
||||
}
|
||||
l = len(m.Uname)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovModel(uint64(l))
|
||||
}
|
||||
l = len(m.Face)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovModel(uint64(l))
|
||||
}
|
||||
if m.HasEmail {
|
||||
n += 2
|
||||
}
|
||||
if m.HasTel {
|
||||
n += 2
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Perm) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Mid != 0 {
|
||||
n += 1 + sovModel(uint64(m.Mid))
|
||||
}
|
||||
if m.AppID != 0 {
|
||||
n += 1 + sovModel(uint64(m.AppID))
|
||||
}
|
||||
if m.AppSubID != 0 {
|
||||
n += 1 + sovModel(uint64(m.AppSubID))
|
||||
}
|
||||
l = len(m.AccessToken)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovModel(uint64(l))
|
||||
}
|
||||
l = len(m.RefreshToken)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovModel(uint64(l))
|
||||
}
|
||||
if m.CreateAt != 0 {
|
||||
n += 1 + sovModel(uint64(m.CreateAt))
|
||||
}
|
||||
if m.Expires != 0 {
|
||||
n += 1 + sovModel(uint64(m.Expires))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovModel(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozModel(x uint64) (n int) {
|
||||
return sovModel(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *Info) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Info: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Info: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Mid", wireType)
|
||||
}
|
||||
m.Mid = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Mid |= (int64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field UserID", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthModel
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.UserID = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Uname", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthModel
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Uname = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Face", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthModel
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Face = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field HasEmail", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.HasEmail = bool(v != 0)
|
||||
case 6:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field HasTel", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.HasTel = bool(v != 0)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipModel(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthModel
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Perm) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Perm: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Perm: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Mid", wireType)
|
||||
}
|
||||
m.Mid = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Mid |= (int64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AppID", wireType)
|
||||
}
|
||||
m.AppID = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.AppID |= (int32(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AppSubID", wireType)
|
||||
}
|
||||
m.AppSubID = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.AppSubID |= (int32(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AccessToken", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthModel
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.AccessToken = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field RefreshToken", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthModel
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.RefreshToken = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 6:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field CreateAt", wireType)
|
||||
}
|
||||
m.CreateAt = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.CreateAt |= (int64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 7:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Expires", wireType)
|
||||
}
|
||||
m.Expires = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Expires |= (int64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipModel(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthModel
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipModel(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthModel
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowModel
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipModel(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthModel = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowModel = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() { proto.RegisterFile("model.proto", fileDescriptorModel) }
|
||||
|
||||
var fileDescriptorModel = []byte{
|
||||
// 409 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0x4f, 0x8e, 0xd3, 0x30,
|
||||
0x14, 0xc6, 0xc9, 0xe4, 0x4f, 0x5b, 0x77, 0x46, 0x1a, 0xbc, 0x0a, 0x08, 0xd5, 0x55, 0x11, 0x52,
|
||||
0x59, 0x30, 0x23, 0x81, 0x38, 0x40, 0xcb, 0x0c, 0x9a, 0x2e, 0x90, 0x90, 0x99, 0xae, 0x2b, 0x27,
|
||||
0x79, 0x6d, 0x23, 0x92, 0xda, 0xb2, 0x13, 0x89, 0xa3, 0x70, 0x06, 0x4e, 0xc2, 0x92, 0x05, 0x6b,
|
||||
0x0b, 0x95, 0x9d, 0x4f, 0x81, 0xf2, 0x1c, 0x2a, 0xd8, 0xcc, 0x2e, 0xef, 0xf7, 0xfb, 0x9e, 0xf4,
|
||||
0x3d, 0x2b, 0x64, 0x5c, 0xcb, 0x02, 0xaa, 0x2b, 0xa5, 0x65, 0x23, 0x69, 0x8c, 0xc3, 0xd3, 0x57,
|
||||
0xbb, 0xb2, 0xd9, 0xb7, 0xd9, 0x55, 0x2e, 0xeb, 0xeb, 0x9d, 0xdc, 0xc9, 0x6b, 0xb4, 0x59, 0xbb,
|
||||
0xc5, 0x09, 0x07, 0xfc, 0xf2, 0x5b, 0xb3, 0x9f, 0x01, 0x89, 0x56, 0x87, 0xad, 0xa4, 0x4f, 0x48,
|
||||
0xf8, 0xa1, 0x2c, 0xd2, 0x60, 0x1a, 0xcc, 0xc3, 0xe5, 0xc0, 0x59, 0x16, 0xd6, 0x65, 0xc1, 0x3b,
|
||||
0x46, 0x67, 0x24, 0x59, 0x1b, 0xd0, 0xab, 0x9b, 0xf4, 0x6c, 0x1a, 0xcc, 0x47, 0x4b, 0xe2, 0x2c,
|
||||
0x4b, 0x5a, 0x03, 0xba, 0x2c, 0x78, 0x6f, 0x28, 0x23, 0xf1, 0xfa, 0x20, 0x6a, 0x48, 0x43, 0x8c,
|
||||
0x8c, 0x9c, 0x65, 0x71, 0xdb, 0x01, 0xee, 0x39, 0x7d, 0x46, 0xa2, 0xf7, 0x22, 0x87, 0x34, 0x42,
|
||||
0x3f, 0x74, 0x96, 0x45, 0x5b, 0x91, 0x03, 0x47, 0x4a, 0x5f, 0x92, 0xe1, 0x9d, 0x30, 0xb7, 0xb5,
|
||||
0x28, 0xab, 0x34, 0x9e, 0x06, 0xf3, 0xe1, 0xf2, 0xc2, 0x59, 0x36, 0xda, 0x0b, 0xb3, 0x81, 0x0e,
|
||||
0xf2, 0x93, 0xa6, 0xcf, 0x49, 0x72, 0x27, 0xcc, 0x3d, 0x54, 0x69, 0x82, 0xc1, 0xb1, 0xb3, 0x6c,
|
||||
0xd0, 0x05, 0x1b, 0xa8, 0x78, 0xaf, 0x66, 0xdf, 0xce, 0x48, 0xf4, 0x11, 0x74, 0xfd, 0xd0, 0x59,
|
||||
0x8c, 0xc4, 0x0b, 0xa5, 0xfa, 0xab, 0x62, 0x5f, 0x59, 0x28, 0x55, 0x16, 0xdc, 0xf3, 0xae, 0xd4,
|
||||
0x42, 0xa9, 0x4f, 0x6d, 0xb6, 0xba, 0xc1, 0xb3, 0x62, 0x5f, 0x4a, 0x28, 0xb5, 0x31, 0x6d, 0x56,
|
||||
0x16, 0xfc, 0xa4, 0xe9, 0x6b, 0x32, 0x5e, 0xe4, 0x39, 0x18, 0x73, 0x2f, 0x3f, 0xc3, 0xa1, 0x3f,
|
||||
0xf2, 0xd2, 0x59, 0x76, 0x2e, 0x10, 0x6f, 0x9a, 0x8e, 0xf3, 0x7f, 0x43, 0xf4, 0x2d, 0x39, 0xe7,
|
||||
0xb0, 0xd5, 0x60, 0xf6, 0x7e, 0x29, 0xc6, 0xa5, 0xc7, 0xce, 0xb2, 0x0b, 0xed, 0x79, 0xbf, 0xf5,
|
||||
0x5f, 0xac, 0x6b, 0xf5, 0x4e, 0x83, 0x68, 0x60, 0xd1, 0xe0, 0x0b, 0x84, 0xbe, 0x55, 0x8e, 0x6c,
|
||||
0x23, 0x1a, 0x7e, 0xd2, 0xf4, 0x05, 0x19, 0xdc, 0x7e, 0x51, 0xa5, 0x06, 0x93, 0x0e, 0x30, 0x89,
|
||||
0x6f, 0x05, 0x1e, 0xf1, 0xbf, 0x6e, 0x79, 0xf9, 0xfd, 0x38, 0x09, 0x7e, 0x1c, 0x27, 0xc1, 0xaf,
|
||||
0xe3, 0x24, 0xf8, 0xfa, 0x7b, 0xf2, 0x28, 0x4b, 0xf0, 0xe7, 0x78, 0xf3, 0x27, 0x00, 0x00, 0xff,
|
||||
0xff, 0x4a, 0x98, 0xa7, 0x40, 0x61, 0x02, 0x00, 0x00,
|
||||
}
|
26
app/service/main/passport-game/model/model.proto
Normal file
26
app/service/main/passport-game/model/model.proto
Normal file
@ -0,0 +1,26 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package model;
|
||||
|
||||
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
|
||||
// Info account info.
|
||||
message Info {
|
||||
int64 Mid = 1 [ (gogoproto.jsontag) = "mid" ];
|
||||
string UserID = 2 [ (gogoproto.jsontag) = "userid" ];
|
||||
string Uname = 3 [ (gogoproto.jsontag) = "uname" ];
|
||||
string Face = 4 [ (gogoproto.jsontag) = "face" ];
|
||||
bool HasEmail = 5 [ (gogoproto.jsontag) = "has_email" ];
|
||||
bool HasTel = 6 [ (gogoproto.jsontag) = "has_tel" ];
|
||||
}
|
||||
|
||||
// Perm token.
|
||||
message Perm {
|
||||
int64 Mid = 1 [ (gogoproto.jsontag) = "mid" ];
|
||||
int32 AppID = 2 [ (gogoproto.jsontag) = "appid" ];
|
||||
int32 AppSubID = 3 [ (gogoproto.jsontag) = "app_subid" ];
|
||||
string AccessToken = 4 [ (gogoproto.jsontag) = "access_token" ];
|
||||
string RefreshToken = 5 [ (gogoproto.jsontag) = "refresh_token" ];
|
||||
int64 CreateAt = 6 [ (gogoproto.jsontag) = "create_at" ];
|
||||
int64 Expires = 7 [ (gogoproto.jsontag) = "expires" ];
|
||||
}
|
8
app/service/main/passport-game/model/open.go
Normal file
8
app/service/main/passport-game/model/open.go
Normal file
@ -0,0 +1,8 @@
|
||||
package model
|
||||
|
||||
// App app info.
|
||||
type App struct {
|
||||
AppID int32 `json:"appid"`
|
||||
AppKey string `json:"appkey"`
|
||||
AppSecret string `json:"app_secret"`
|
||||
}
|
5
app/service/main/passport-game/model/proto.sh
Normal file
5
app/service/main/passport-game/model/proto.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#! /bin/sh
|
||||
# proto.sh
|
||||
gopath=$GOPATH/src
|
||||
gogopath=$GOPATH/src/go-common/vendor/github.com/gogo/protobuf
|
||||
protoc --gofast_out=. --proto_path=$gopath:$gogopath:. *.proto
|
80
app/service/main/passport-game/service/BUILD
Normal file
80
app/service/main/passport-game/service/BUILD
Normal file
@ -0,0 +1,80 @@
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"account.go",
|
||||
"cache.go",
|
||||
"md5.go",
|
||||
"passport.go",
|
||||
"passport_key.go",
|
||||
"passport_login.go",
|
||||
"passport_oauth.go",
|
||||
"passport_reg.go",
|
||||
"passport_renew_token.go",
|
||||
"region.go",
|
||||
"rsa.go",
|
||||
"rsa_time_hash.go",
|
||||
"service.go",
|
||||
],
|
||||
importpath = "go-common/app/service/main/passport-game/service",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/service/main/passport-game/conf:go_default_library",
|
||||
"//app/service/main/passport-game/dao:go_default_library",
|
||||
"//app/service/main/passport-game/model:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/stat:go_default_library",
|
||||
"//library/stat/prom:go_default_library",
|
||||
"//library/sync/errgroup:go_default_library",
|
||||
"//vendor/github.com/satori/go.uuid:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"account_test.go",
|
||||
"md5_test.go",
|
||||
"passport_key_test.go",
|
||||
"passport_login_test.go",
|
||||
"passport_oauth_test.go",
|
||||
"passport_reg_test.go",
|
||||
"passport_renew_token_test.go",
|
||||
"passport_test.go",
|
||||
"region_test.go",
|
||||
"rsa_test.go",
|
||||
"rsa_time_hash_test.go",
|
||||
"service_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
rundir = ".",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//app/service/main/passport-game/conf:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//vendor/github.com/satori/go.uuid:go_default_library",
|
||||
"//vendor/github.com/smartystreets/goconvey/convey: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"],
|
||||
)
|
74
app/service/main/passport-game/service/account.go
Normal file
74
app/service/main/passport-game/service/account.go
Normal file
@ -0,0 +1,74 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/library/sync/errgroup"
|
||||
)
|
||||
|
||||
// MyInfo get user's info by token.
|
||||
func (s *Service) MyInfo(c context.Context, app *model.App, accessKey string) (*model.Info, error) {
|
||||
ti, err := s.thinOauth(c, app, accessKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Info(c, ti.Mid), nil
|
||||
}
|
||||
|
||||
// Info get user's info by mid.
|
||||
func (s *Service) Info(c context.Context, mid int64) (res *model.Info) {
|
||||
var err error
|
||||
cache := true
|
||||
if res, err = s.d.InfoCache(c, mid); err != nil {
|
||||
err = nil
|
||||
cache = false
|
||||
} else if res != nil {
|
||||
return
|
||||
}
|
||||
var userid, uname, face string
|
||||
var email, tel *string
|
||||
eg, errCtx := errgroup.WithContext(c)
|
||||
eg.Go(func() (err error) {
|
||||
accInfo, err := s.d.AccountInfo(errCtx, mid)
|
||||
if err != nil || accInfo == nil {
|
||||
userid = model.DefaultUserID(mid)
|
||||
uname = model.DefaultUname(mid)
|
||||
return
|
||||
}
|
||||
userid = accInfo.UserID
|
||||
uname = accInfo.Uname
|
||||
email = accInfo.Email
|
||||
tel = accInfo.Tel
|
||||
return
|
||||
})
|
||||
eg.Go(func() (err error) {
|
||||
memInfo, err := s.d.MemberInfo(errCtx, mid)
|
||||
if err != nil || memInfo == nil {
|
||||
face = model.EmptyFace
|
||||
return
|
||||
}
|
||||
face = memInfo.FullFace()
|
||||
return
|
||||
})
|
||||
eg.Wait()
|
||||
info := &model.Info{
|
||||
Mid: mid,
|
||||
UserID: userid,
|
||||
Uname: uname,
|
||||
Face: face,
|
||||
}
|
||||
if email != nil {
|
||||
info.HasEmail = true
|
||||
}
|
||||
if tel != nil {
|
||||
info.HasTel = true
|
||||
}
|
||||
if cache {
|
||||
s.addCache(func() {
|
||||
s.d.SetInfoCache(context.Background(), info)
|
||||
})
|
||||
}
|
||||
res = info
|
||||
return
|
||||
}
|
28
app/service/main/passport-game/service/account_test.go
Normal file
28
app/service/main/passport-game/service/account_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
_gameAppKey = "d4761645d1632e8c"
|
||||
)
|
||||
|
||||
// TestService_MyInfo oauth via origin.
|
||||
func TestService_MyInfo(t *testing.T) {
|
||||
once.Do(startService)
|
||||
ak := "4de8aecfafc7f91cb650d6371efb1b63"
|
||||
expectMid := int64(110000139)
|
||||
if res, err := s.MyInfo(context.TODO(), s.appMap[_gameAppKey], ak); err != nil {
|
||||
t.Errorf("s.MyInfo() error(%v)", err)
|
||||
t.FailNow()
|
||||
} else if res == nil || res.Mid != expectMid {
|
||||
t.Errorf("res is not correct, expected res with mid %d but got %v", expectMid, res)
|
||||
t.FailNow()
|
||||
} else {
|
||||
str, _ := json.Marshal(res)
|
||||
t.Logf("res: %s", str)
|
||||
}
|
||||
}
|
17
app/service/main/passport-game/service/cache.go
Normal file
17
app/service/main/passport-game/service/cache.go
Normal file
@ -0,0 +1,17 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
)
|
||||
|
||||
// TokenPBCache get token pb cache.
|
||||
func (s *Service) TokenPBCache(c context.Context, key string) (res *model.Perm, err error) {
|
||||
return s.d.TokenPBCache(c, key)
|
||||
}
|
||||
|
||||
// InfoPBCache get info pb cache.
|
||||
func (s *Service) InfoPBCache(c context.Context, key string) (res *model.Info, err error) {
|
||||
return s.d.InfoPBCache(c, key)
|
||||
}
|
27
app/service/main/passport-game/service/md5.go
Normal file
27
app/service/main/passport-game/service/md5.go
Normal file
@ -0,0 +1,27 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func md5Hex(s string) string {
|
||||
sum := md5.Sum([]byte(s))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
// MD52IntStr converts MD5 checksum bytes to big int string in base 10.
|
||||
func MD52IntStr(md5d []byte) (res string) {
|
||||
b := big.NewInt(0)
|
||||
b.SetBytes(md5d)
|
||||
res = b.Text(10)
|
||||
return
|
||||
}
|
||||
|
||||
// IntStr2Md5 converts big int string in base 10 to MD5 checksum bytes.
|
||||
func IntStr2Md5(intStr string) (res []byte) {
|
||||
b := big.NewInt(0)
|
||||
b.SetString(intStr, 10)
|
||||
return b.Bytes()
|
||||
}
|
21
app/service/main/passport-game/service/md5_test.go
Normal file
21
app/service/main/passport-game/service/md5_test.go
Normal file
@ -0,0 +1,21 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMD52IntStr(t *testing.T) {
|
||||
md5d := md5.Sum([]byte("foo"))
|
||||
intStr := MD52IntStr(md5d[:])
|
||||
md5dAfter := IntStr2Md5(intStr)
|
||||
if !bytes.Equal(md5d[:], md5dAfter) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestClout(t *testing.T) {
|
||||
fmt.Println(md5Hex(fmt.Sprintf("%s>>BiLiSaLt<<%s", md5Hex("prFP8dF2z1"), "bBTXzlsT")))
|
||||
}
|
42
app/service/main/passport-game/service/passport.go
Normal file
42
app/service/main/passport-game/service/passport.go
Normal file
@ -0,0 +1,42 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
)
|
||||
|
||||
const (
|
||||
_expireSeconds = 2592000 // 30 days
|
||||
_gameAdditionalExpireSeconds = 1296000 // 15 days
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrDispatcherError dispatcher error
|
||||
ErrDispatcherError = errors.New("dispatcher route map is error")
|
||||
)
|
||||
|
||||
func (s *Service) tokenInfo(c context.Context, accessKey string) (token *model.Perm, err error) {
|
||||
cache := true
|
||||
if token, err = s.d.TokenCache(c, accessKey); err != nil {
|
||||
err = nil
|
||||
cache = false
|
||||
} else if token != nil {
|
||||
return
|
||||
}
|
||||
if token, err = s.d.Token(c, accessKey); err != nil {
|
||||
return
|
||||
}
|
||||
if cache && token != nil {
|
||||
s.addCache(func() {
|
||||
s.d.SetTokenCache(context.TODO(), token)
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Proxy if login and getKey via model api.
|
||||
func (s *Service) Proxy(c context.Context) (res bool) {
|
||||
return s.proxy
|
||||
}
|
47
app/service/main/passport-game/service/passport_key.go
Normal file
47
app/service/main/passport-game/service/passport_key.go
Normal file
@ -0,0 +1,47 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
)
|
||||
|
||||
const (
|
||||
_originPubKey = "-----BEGIN PUBLIC KEY-----\n" +
|
||||
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdScM09sZJqFPX7bvmB2y6i08J\n" +
|
||||
"bHsa0v4THafPbJN9NoaZ9Djz1LmeLkVlmWx1DwgHVW+K7LVWT5FV3johacVRuV98\n" +
|
||||
"37+RNntEK6SE82MPcl7fA++dmW2cLlAjsIIkrX+aIvvSGCuUfcWpWFy3YVDqhuHr\n" +
|
||||
"NDjdNcaefJIQHMW+sQIDAQAB\n" +
|
||||
"-----END PUBLIC KEY-----\n"
|
||||
|
||||
_originPrivKey = "-----BEGIN PRIVATE KEY-----\n" +
|
||||
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJ1JwzT2xkmoU9ft\n" +
|
||||
"u+YHbLqLTwlsexrS/hMdp89sk302hpn0OPPUuZ4uRWWZbHUPCAdVb4rstVZPkVXe\n" +
|
||||
"OiFpxVG5X3zfv5E2e0QrpITzYw9yXt8D752ZbZwuUCOwgiStf5oi+9IYK5R9xalY\n" +
|
||||
"XLdhUOqG4es0ON01xp58khAcxb6xAgMBAAECgYAsBeQ8I8HWBeYJrsGDnZpiD/G8\n" +
|
||||
"On+uP1XbtdYtKT+SsTs1RfTW0jhtvJex2yJPFTjzDIeew6fxk22jMgLlLTyLtc+H\n" +
|
||||
"LFmNt6/5DIxeSslx0cZOJW2w1KLyzPBIVQ+q1rAu4wZx4LSTFzAHQGWkGH3352Nj\n" +
|
||||
"40GIMOMOLrOReb8/rQJBAM4S8mChP9NAWvjSyQY4jqHQsCmcDeV1Tuwo5jxeMMZ5\n" +
|
||||
"YSrtwEEaLN4mkvpMeQR60RtjdJXxfySJY0lF/e5RZ7sCQQDDZQjUmry41Ar6uSGj\n" +
|
||||
"OrZADOSmqZy0qCijgthkN2Gblx9eyFFMFcakJECF/m2zUo5MeqKu5RTDXBZt0b3l\n" +
|
||||
"JV6DAkEAnIv0KMgWbmsDMOcf42PvpqmcSd/NBrU5AVqInO+I6h2nXS9Dz7EMyK5R\n" +
|
||||
"FWgmvup2E/JXzNiql5zvGejb4MFipQJAVScl5wmcb2wxcLzXtPw0SsuTpjJK0cxr\n" +
|
||||
"EX9HcL1V82mzySnBjEf9LrGB0SNliX3T9+6GEXRSTSVHvQpoGIHlowJBAKJBTxKi\n" +
|
||||
"9ypIdK1mA7kw8+g+YdXliov5B2MMe1yaGyGjz3YGQ8N1YLBK6Yp4KOwodFurmgcX\n" +
|
||||
"ozLanqOwPdNW1Nk=\n" +
|
||||
"-----END PRIVATE KEY-----\n"
|
||||
)
|
||||
|
||||
// RSAKeyOrigin get rsa key via model api.
|
||||
func (s *Service) RSAKeyOrigin(c context.Context) (res *model.RSAKey, err error) {
|
||||
return s.d.RSAKeyOrigin(c)
|
||||
}
|
||||
|
||||
// RSAKey get cloud rsa pub key and seconds ts hash.
|
||||
func (s *Service) RSAKey(c context.Context) *model.RSAKey {
|
||||
return &model.RSAKey{
|
||||
Hash: TsSeconds2Hash(time.Now().Unix()),
|
||||
Key: _originPubKey,
|
||||
}
|
||||
}
|
27
app/service/main/passport-game/service/passport_key_test.go
Normal file
27
app/service/main/passport-game/service/passport_key_test.go
Normal file
@ -0,0 +1,27 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestService_RSAKey(t *testing.T) {
|
||||
once.Do(startService)
|
||||
originRSA, err := s.RSAKeyOrigin(context.TODO())
|
||||
if err != nil {
|
||||
t.Errorf("failed to get origin public key, service.RSAKeyOrigin() error(%v)", err)
|
||||
t.FailNow()
|
||||
} else {
|
||||
str, _ := json.Marshal(originRSA)
|
||||
t.Logf("cloud RSA: %s", str)
|
||||
}
|
||||
cloudRSA := s.RSAKey(context.TODO())
|
||||
if cloudRSA.Key == originRSA.Key {
|
||||
t.Errorf("cloud RSA public key cannot be equal to origin RSA public key")
|
||||
t.FailNow()
|
||||
} else {
|
||||
str, _ := json.Marshal(cloudRSA)
|
||||
t.Logf("cloud RSA: %s", str)
|
||||
}
|
||||
}
|
215
app/service/main/passport-game/service/passport_login.go
Normal file
215
app/service/main/passport-game/service/passport_login.go
Normal file
@ -0,0 +1,215 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
|
||||
"github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
_tsHashLen = 16
|
||||
_rsaTimeoutSeconds = 20
|
||||
|
||||
_asoPasswordError = -627
|
||||
)
|
||||
|
||||
// Login login via cloud, if err occurred, via origin.
|
||||
func (s *Service) Login(c context.Context, app *model.App, subid int32, userid, rsaPwd string) (res *model.LoginToken, err error) {
|
||||
if userid == "" || rsaPwd == "" {
|
||||
err = ecode.UsernameOrPasswordErr
|
||||
return
|
||||
}
|
||||
cache := true
|
||||
a, pwd, tsHash, err := s.checkUserData(c, userid, rsaPwd)
|
||||
if err != nil {
|
||||
if err == ecode.PasswordHashExpires || err == ecode.PasswordTooLeak {
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
} else {
|
||||
var t *model.Perm
|
||||
if t, cache, err = s.saveToken(c, app.AppID, subid, a.Mid); err != nil {
|
||||
err = nil
|
||||
} else {
|
||||
res = &model.LoginToken{
|
||||
Mid: t.Mid,
|
||||
AccessKey: t.AccessToken,
|
||||
Expires: t.Expires,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
if res, err = s.loginOrigin(c, userid, pwd, tsHash); err != nil {
|
||||
return
|
||||
}
|
||||
if cache && res != nil {
|
||||
s.d.SetTokenCache(c, &model.Perm{
|
||||
Mid: res.Mid,
|
||||
AppID: app.AppID,
|
||||
AppSubID: subid,
|
||||
AccessToken: res.AccessKey,
|
||||
CreateAt: res.Expires - _expireSeconds,
|
||||
Expires: res.Expires,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) checkUserData(c context.Context, userid, rsaPwd string) (a *model.AsoAccount, pwd, tsHash string, err error) {
|
||||
if tsHash, pwd, err = s.parseRSAPwd(rsaPwd); err != nil {
|
||||
return
|
||||
}
|
||||
if timeout(time.Now().Unix(), tsHash) {
|
||||
err = ecode.PasswordHashExpires
|
||||
return
|
||||
}
|
||||
if pwd == "" {
|
||||
err = ecode.UsernameOrPasswordErr
|
||||
return
|
||||
}
|
||||
if a, err = s.asoAccountInfo(c, userid); err != nil {
|
||||
return
|
||||
}
|
||||
// TODO 2017.12.27 when leak business changes, update here
|
||||
if a.Leak() {
|
||||
err = ecode.PasswordTooLeak
|
||||
return
|
||||
}
|
||||
if pwd == "" {
|
||||
err = ecode.UsernameOrPasswordErr
|
||||
return
|
||||
}
|
||||
if !pwdMatches(pwd, a.Salt, a.Pwd) {
|
||||
err = ecode.UsernameOrPasswordErr
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) parseRSAPwd(rsaPwd string) (tsHash, pwd string, err error) {
|
||||
if len(rsaPwd) < 88 {
|
||||
err = ecode.UsernameOrPasswordErr
|
||||
return
|
||||
}
|
||||
var tsHashPwd string
|
||||
if tsHashPwd, err = s.rsaDecrypt(rsaPwd); err != nil {
|
||||
return
|
||||
}
|
||||
if len(tsHashPwd) < _tsHashLen {
|
||||
err = ecode.UsernameOrPasswordErr
|
||||
return
|
||||
}
|
||||
tsHash = tsHashPwd[:_tsHashLen]
|
||||
pwd = tsHashPwd[_tsHashLen:]
|
||||
return
|
||||
}
|
||||
|
||||
// asoAccountInfo get user info by userid or hash.
|
||||
func (s *Service) asoAccountInfo(c context.Context, userid string) (info *model.AsoAccount, err error) {
|
||||
var acs []*model.AsoAccount
|
||||
if acs, err = s.d.AsoAccount(c, userid, model.DefaultHash(userid)); err != nil {
|
||||
return
|
||||
}
|
||||
if len(acs) == 0 {
|
||||
err = ecode.UserNotExist
|
||||
return
|
||||
}
|
||||
if len(acs) > 1 {
|
||||
err = ecode.UserDuplicate
|
||||
return
|
||||
}
|
||||
info = acs[0]
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) rsaDecrypt(rsaPwd string) (res string, err error) {
|
||||
rs, err := base64.StdEncoding.DecodeString(rsaPwd)
|
||||
if err != nil {
|
||||
log.Error("failed to base64 decode RSA pwd for cloud, error(%v)", err)
|
||||
return
|
||||
}
|
||||
d, err := rsaDecryptPKCS8(s.cloudRSAKey.priv, rs)
|
||||
if err != nil {
|
||||
log.Error("failed to decrypt RSA pwd for cloud, error(%v)", err)
|
||||
return
|
||||
}
|
||||
res = string(d)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) originRSAEncrypt(pwd string, timeHash string) (res string, err error) {
|
||||
ed, err := rsaEncryptPKCS8(s.originPubKey, []byte(timeHash+pwd))
|
||||
if err != nil {
|
||||
log.Error("failed to RSA encrypt pwd for origin, error(%v)", err)
|
||||
return
|
||||
}
|
||||
res = base64.StdEncoding.EncodeToString(ed)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) loginOrigin(c context.Context, userid, pwd, tsHash string) (res *model.LoginToken, err error) {
|
||||
rsaPwd, err := s.originRSAEncrypt(pwd, tsHash)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res, err = s.d.LoginOrigin(c, userid, rsaPwd)
|
||||
if ecode.Cause(err).Code() == _asoPasswordError {
|
||||
err = ecode.UsernameOrPasswordErr
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func timeout(now int64, rsaTimeHash string) bool {
|
||||
ts, err := Hash2TsSeconds(rsaTimeHash)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return now-ts > _rsaTimeoutSeconds
|
||||
}
|
||||
|
||||
// pwdMatches check if password matches.
|
||||
// NOTE: since passport did not use salt in matching password in early period,
|
||||
// those accounts which registered that time and never changed
|
||||
// after passport start to use salt have empty salt,
|
||||
// the schema for generating password hash in passport origin is:
|
||||
// if the salt is empty, take the result of md5Hex(plain) as password hash,
|
||||
// else take the result of fmt.Sprintf("%s>>BiLiSaLt<<%s", md5Hex(plainPwd), salt) as password hash.
|
||||
func pwdMatches(plainPwd, salt, cloudPwdHash string) bool {
|
||||
if salt == "" {
|
||||
return model.DefaultHash(md5Hex(plainPwd)) == cloudPwdHash
|
||||
}
|
||||
return model.DefaultHash(md5Hex(fmt.Sprintf("%s>>BiLiSaLt<<%s", md5Hex(plainPwd), salt))) == cloudPwdHash
|
||||
}
|
||||
|
||||
func (s *Service) saveToken(c context.Context, appid, subid int32, mid int64) (res *model.Perm, cache bool, err error) {
|
||||
cache = true
|
||||
now := time.Now().Unix()
|
||||
token := &model.Perm{
|
||||
Mid: mid,
|
||||
AppID: appid,
|
||||
AppSubID: subid,
|
||||
AccessToken: md5Hex(fmt.Sprintf("%d,%s", mid, uuid.NewV4().String())) + _segmentation + s.currentRegion,
|
||||
CreateAt: now,
|
||||
Expires: now + _expireSeconds,
|
||||
}
|
||||
if _, err = s.d.AddToken(c, token); err != nil {
|
||||
return
|
||||
}
|
||||
res = token
|
||||
if err = s.d.SetTokenCache(c, token); err != nil {
|
||||
err = nil
|
||||
cache = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// LoginOrigin login via passport api.
|
||||
func (s *Service) LoginOrigin(c context.Context, query, cookie string) (res *model.LoginToken, err error) {
|
||||
return s.d.Login(c, query, cookie)
|
||||
}
|
184
app/service/main/passport-game/service/passport_login_test.go
Normal file
184
app/service/main/passport-game/service/passport_login_test.go
Normal file
@ -0,0 +1,184 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/library/log"
|
||||
|
||||
"github.com/satori/go.uuid"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestPwdMatches(t *testing.T) {
|
||||
Convey("check pwd match when", t, func() {
|
||||
Convey("password is incorrect", func() {
|
||||
Convey("salt is empty", func() {
|
||||
plain := "wrongPassword"
|
||||
salt := ""
|
||||
cloudRsaPwd := "b602e55952dfc534e222577eee8f469e"
|
||||
|
||||
ok := pwdMatches(plain, salt, cloudRsaPwd)
|
||||
So(ok, ShouldBeFalse)
|
||||
})
|
||||
|
||||
Convey("salt is not empty", func() {
|
||||
plain := "wrongPassword"
|
||||
salt := "DC2q1ju5"
|
||||
cloudRsaPwd := "3cb9ffbfd219772793d860c97a815e4b"
|
||||
|
||||
ok := pwdMatches(plain, salt, cloudRsaPwd)
|
||||
So(ok, ShouldBeFalse)
|
||||
})
|
||||
})
|
||||
Convey("password is correct", func() {
|
||||
Convey("salt is empty", func() {
|
||||
plain := "123456"
|
||||
salt := ""
|
||||
cloudRsaPwd := "b602e55952dfc534e222577eee8f469e"
|
||||
|
||||
ok := pwdMatches(plain, salt, cloudRsaPwd)
|
||||
So(ok, ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("salt is not empty", func() {
|
||||
plain := "123456"
|
||||
salt := "DC2q1ju5"
|
||||
cloudRsaPwd := "3cb9ffbfd219772793d860c97a815e4b"
|
||||
|
||||
ok := pwdMatches(plain, salt, cloudRsaPwd)
|
||||
So(ok, ShouldBeTrue)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// TestService_Login_OK login ok.
|
||||
func TestService_Login_OK(t *testing.T) {
|
||||
once.Do(startService)
|
||||
u := "game0033"
|
||||
pwdPlain := "123456"
|
||||
expectMid := int64(110000139)
|
||||
ts := time.Now().Unix()
|
||||
rsaPwd, err := s.rsaEncrypt(TsSeconds2Hash(ts), pwdPlain)
|
||||
if err != nil {
|
||||
t.Errorf("faied to RSA encrypt pwd and ts, rsaEncrypt(%s, %d) error(%v)", pwdPlain, ts, err)
|
||||
t.FailNow()
|
||||
}
|
||||
if res, err := s.Login(context.TODO(), s.appMap[_gameAppKey], 0, u, rsaPwd); err != nil {
|
||||
t.Errorf("service.Login() error(%v)", err)
|
||||
t.FailNow()
|
||||
} else if res == nil || res.Mid != expectMid {
|
||||
t.Errorf("res is not correct, expected login token with mid %d but got %v", expectMid, res)
|
||||
t.FailNow()
|
||||
} else {
|
||||
str, _ := json.Marshal(res)
|
||||
t.Logf("res: %s", str)
|
||||
}
|
||||
}
|
||||
|
||||
// TestService_Login_BackOriginWhenCloudFail when cloud login not ok,
|
||||
// should back origin.
|
||||
func TestService_Login_BackOriginWhenCloudFail(t *testing.T) {
|
||||
once.Do(startService)
|
||||
u := "test_ss"
|
||||
pwdPlain := "123456"
|
||||
ts := time.Now().Unix()
|
||||
rsaPwd, err := s.rsaEncrypt(TsSeconds2Hash(ts), pwdPlain)
|
||||
if err != nil {
|
||||
t.Errorf("faied to RSA encrypt pwd and ts, rsaEncrypt(%s, %d) error(%v)", pwdPlain, ts, err)
|
||||
t.FailNow()
|
||||
}
|
||||
if _, err := s.Login(context.TODO(), s.appMap[_gameAppKey], 0, u, rsaPwd); err != nil {
|
||||
t.Errorf("back origin falied, service.Login() error(%v)", err)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_LoginOrigin(t *testing.T) {
|
||||
once.Do(startService)
|
||||
u := "game0033"
|
||||
pwdPlain := "123456"
|
||||
expectMid := int64(110000139)
|
||||
tsHash := TsSeconds2Hash(time.Now().Unix())
|
||||
if res, err := s.loginOrigin(context.TODO(), u, pwdPlain, tsHash); err != nil {
|
||||
t.Errorf("s.loginOrigin(%s, %s, %s) error(%v)", u, pwdPlain, tsHash, err)
|
||||
t.FailNow()
|
||||
} else if res == nil || res.Mid != expectMid {
|
||||
t.Errorf("res is not correct, expected login token with mid %d but got %v", expectMid, res)
|
||||
t.FailNow()
|
||||
} else {
|
||||
str, _ := json.Marshal(res)
|
||||
t.Logf("res: %v", string(str))
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_RSADecrypt(t *testing.T) {
|
||||
once.Do(startService)
|
||||
expect := "123456"
|
||||
rsaPwd, err := s.rsaEncrypt(TsSeconds2Hash(time.Now().Unix()), expect)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
res, err := s.rsaDecrypt(rsaPwd)
|
||||
if err != nil {
|
||||
t.Errorf("failed to decrypt, error(%v)", err)
|
||||
t.FailNow()
|
||||
}
|
||||
ts, _ := Hash2TsSeconds(res[:16])
|
||||
plain := res[16:]
|
||||
if plain != expect {
|
||||
t.Errorf("expect plain %s but got %s", expect, plain)
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("ts hash: %s, ts: %d, plain: %s", res[:16], ts, res[16:])
|
||||
}
|
||||
|
||||
func BenchmarkService_RSADecrypt(b *testing.B) {
|
||||
once.Do(startService)
|
||||
minLen := 3
|
||||
maxLen := 16
|
||||
num := maxLen - minLen + 1
|
||||
plains := make([]string, num)
|
||||
cipers := make([]string, num)
|
||||
for i := 0; i < num; i++ {
|
||||
u := strings.Replace(uuid.NewV4().String(), "-", "", 4)
|
||||
plains[i] = u[:i+minLen]
|
||||
cb, err := rsaEncryptPKCS8(s.cloudRSAKey.pub, []byte(plains[i]))
|
||||
if err != nil {
|
||||
b.FailNow()
|
||||
}
|
||||
cipers[i] = base64.StdEncoding.EncodeToString(cb)
|
||||
}
|
||||
atomicCnt := int64(0)
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
idx := atomic.AddInt64(&atomicCnt, 1) % int64(num)
|
||||
res, err := s.rsaDecrypt(cipers[idx])
|
||||
if err != nil {
|
||||
b.Errorf("s.rsaDecrypt(%s) error(%v)", cipers[idx], err)
|
||||
b.FailNow()
|
||||
}
|
||||
if res != plains[idx] {
|
||||
b.Errorf("expect %s but got %s", plains[idx], res)
|
||||
b.FailNow()
|
||||
}
|
||||
}
|
||||
})
|
||||
b.ReportAllocs()
|
||||
}
|
||||
|
||||
func (s *Service) rsaEncrypt(timeHash, pwd string) (res string, err error) {
|
||||
d, err := rsaEncryptPKCS8(s.cloudRSAKey.pub, []byte(timeHash+pwd))
|
||||
if err != nil {
|
||||
log.Error("failed to encrypt pwd, error(%v)", err)
|
||||
return
|
||||
}
|
||||
res = base64.StdEncoding.EncodeToString(d)
|
||||
return
|
||||
}
|
178
app/service/main/passport-game/service/passport_oauth.go
Normal file
178
app/service/main/passport-game/service/passport_oauth.go
Normal file
@ -0,0 +1,178 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
// Oauth oauth.
|
||||
func (s *Service) Oauth(c context.Context, app *model.App, accessToken, from string) (token *model.Token, err error) {
|
||||
if accessToken == "" {
|
||||
err = ecode.AccessKeyErr
|
||||
return
|
||||
}
|
||||
region, ok := region(accessToken)
|
||||
if !ok {
|
||||
err = ecode.AccessKeyErr
|
||||
return
|
||||
}
|
||||
if region == s.currentRegion {
|
||||
return s.currentOauth(c, accessToken)
|
||||
}
|
||||
if region == _origin {
|
||||
token, err = s.currentOauth(c, accessToken)
|
||||
} else {
|
||||
token, err = s.otherOauth(c, accessToken)
|
||||
}
|
||||
if err == nil && token != nil && token.Mid > 0 {
|
||||
return
|
||||
}
|
||||
if from != "" {
|
||||
s.dispatcherErrStats.Incr("dispatcher_error")
|
||||
err = ErrDispatcherError
|
||||
return
|
||||
}
|
||||
return s.originOauth(c, s.oauth[region], accessToken, s.currentRegion)
|
||||
}
|
||||
|
||||
func (s *Service) originOauth(c context.Context, uri, accessKey, from string) (*model.Token, error) {
|
||||
cache := true
|
||||
token, err := s.d.OriginTokenCache(c, accessKey)
|
||||
if token != nil {
|
||||
if token.Mid > 0 {
|
||||
return token, nil
|
||||
}
|
||||
return nil, ecode.NoLogin
|
||||
}
|
||||
if err != nil {
|
||||
cache = false
|
||||
log.Error("Faield to get origin token cache with access key: %s: %+v", accessKey, err)
|
||||
}
|
||||
token, err = s.d.Oauth(c, uri, accessKey, from)
|
||||
if token != nil {
|
||||
// s.addCache(func() { s.d.SetOriginTokenCache(context.Background(), token) })
|
||||
return token, nil
|
||||
}
|
||||
|
||||
log.Error("Failed to oauth token by origin: %s, %s, %s: %+v", uri, accessKey, from, err)
|
||||
if !cache {
|
||||
return nil, err
|
||||
}
|
||||
if ec := ecode.Cause(err); ec.Equal(ecode.AccessKeyErr) || ec.Equal(ecode.NoLogin) {
|
||||
token = &model.Token{
|
||||
Mid: -1,
|
||||
AccessToken: accessKey,
|
||||
}
|
||||
s.addCache(func() { s.d.SetOriginTokenCache(context.Background(), token) })
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (s *Service) currentOauth(c context.Context, accessToken string) (token *model.Token, err error) {
|
||||
var t *model.Perm
|
||||
if t, err = s.tokenInfo(c, accessToken); err != nil {
|
||||
err = nil
|
||||
}
|
||||
return s.parseToken(c, t)
|
||||
}
|
||||
|
||||
func (s *Service) otherOauth(c context.Context, accessToken string) (token *model.Token, err error) {
|
||||
var t *model.Perm
|
||||
if t, err = s.d.TokenFromOtherRegion(c, accessToken); err != nil {
|
||||
err = nil
|
||||
}
|
||||
return s.parseToken(c, t)
|
||||
}
|
||||
|
||||
func (s *Service) parseToken(c context.Context, t *model.Perm) (token *model.Token, err error) {
|
||||
if t == nil {
|
||||
err = ecode.AccessKeyErr
|
||||
return
|
||||
}
|
||||
duration := time.Now().Unix() - t.Expires
|
||||
if duration > _gameAdditionalExpireSeconds {
|
||||
err = ecode.AccessKeyErr
|
||||
return
|
||||
}
|
||||
if duration > 0 && duration <= _gameAdditionalExpireSeconds {
|
||||
err = ecode.AccessTokenExpires
|
||||
return
|
||||
}
|
||||
accInfo := s.Info(c, t.Mid)
|
||||
token = &model.Token{
|
||||
Mid: t.Mid,
|
||||
AppID: t.AppID,
|
||||
AccessToken: t.AccessToken,
|
||||
CreateAt: t.CreateAt,
|
||||
UserID: accInfo.UserID,
|
||||
Uname: accInfo.Uname,
|
||||
Expires: t.Expires,
|
||||
Permission: "ALL",
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// thinOauth oauth and return mid.
|
||||
func (s *Service) thinOauth(c context.Context, app *model.App, accessToken string) (res *model.Info, err error) {
|
||||
if accessToken == "" {
|
||||
err = ecode.AccessKeyErr
|
||||
return
|
||||
}
|
||||
region, ok := region(accessToken)
|
||||
if !ok {
|
||||
err = ecode.AccessKeyErr
|
||||
return
|
||||
}
|
||||
var mid int64
|
||||
if region == s.currentRegion {
|
||||
mid, err = s.thinCurrentOauth(c, app.AppKey, accessToken)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res = &model.Info{
|
||||
Mid: mid,
|
||||
}
|
||||
return
|
||||
}
|
||||
if region == _origin {
|
||||
mid, err = s.thinCurrentOauth(c, app.AppKey, accessToken)
|
||||
if err == nil {
|
||||
res = &model.Info{
|
||||
Mid: mid,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
t, err := s.d.Oauth(c, s.oauth[region], accessToken, s.currentRegion)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res = &model.Info{
|
||||
Mid: t.Mid,
|
||||
UserID: t.UserID,
|
||||
Uname: t.Uname,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) thinCurrentOauth(c context.Context, appKey, accessToken string) (res int64, err error) {
|
||||
var t *model.Perm
|
||||
if t, err = s.tokenInfo(c, accessToken); err != nil {
|
||||
err = nil
|
||||
}
|
||||
if t == nil {
|
||||
err = ecode.AccessKeyErr
|
||||
return
|
||||
}
|
||||
duration := time.Now().Unix() - t.Expires
|
||||
if duration > 0 && duration <= _gameAdditionalExpireSeconds {
|
||||
err = ecode.AccessTokenExpires
|
||||
return
|
||||
}
|
||||
res = t.Mid
|
||||
return
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"go-common/library/ecode"
|
||||
)
|
||||
|
||||
func TestService_Oauth(t *testing.T) {
|
||||
once.Do(startService)
|
||||
ak := "4de8aecfafc7f91cb650d6371efb1b63"
|
||||
expectMid := int64(110000139)
|
||||
if res, err := s.Oauth(context.TODO(), s.appMap[_gameAppKey], ak, ""); err != nil {
|
||||
t.Errorf("s.Oauth() error(%v)", err)
|
||||
t.FailNow()
|
||||
} else if res == nil || res.Mid != expectMid {
|
||||
t.Errorf("res is not correct, expected res with mid %d but got %v", expectMid, res)
|
||||
t.FailNow()
|
||||
} else {
|
||||
str, _ := json.Marshal(res)
|
||||
t.Logf("res: %s", str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_Oauth_Expires(t *testing.T) {
|
||||
once.Do(startService)
|
||||
ak := "c1e220e12fd4c89a0c5449b9f8c7b062"
|
||||
if _, err := s.Oauth(context.TODO(), s.appMap[_gameAppKey], ak, ""); err != ecode.AccessTokenExpires {
|
||||
t.Errorf("res is not correct, expected error %v, but got %v", ecode.AccessTokenExpires, err)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
43
app/service/main/passport-game/service/passport_reg.go
Normal file
43
app/service/main/passport-game/service/passport_reg.go
Normal file
@ -0,0 +1,43 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
)
|
||||
|
||||
// RegV3 RegV3
|
||||
func (s *Service) RegV3(c context.Context, tdoRegV3 model.TdoRegV3) (regV3 *model.ResRegV3, err error) {
|
||||
regV3, err = s.d.RegV3(c, tdoRegV3)
|
||||
return
|
||||
}
|
||||
|
||||
// RegV2 RegV2
|
||||
func (s *Service) RegV2(c context.Context, tdoRegV2 model.TdoRegV2) (regV2 *model.ResRegV2, err error) {
|
||||
regV2, err = s.d.RegV2(c, tdoRegV2)
|
||||
return
|
||||
}
|
||||
|
||||
// Reg Reg
|
||||
func (s *Service) Reg(c context.Context, tdoReg model.TdoReg) (reg *model.ResReg, err error) {
|
||||
reg, err = s.d.Reg(c, tdoReg)
|
||||
return
|
||||
}
|
||||
|
||||
// ByTel ByTel
|
||||
func (s *Service) ByTel(c context.Context, tdoByTel model.TdoByTel) (byTel *model.ResByTel, err error) {
|
||||
byTel, err = s.d.ByTel(c, tdoByTel)
|
||||
return
|
||||
}
|
||||
|
||||
// Captcha Captcha
|
||||
func (s *Service) Captcha(c context.Context, ip string) (captchaData *model.CaptchaData, err error) {
|
||||
captchaData, err = s.d.Captcha(c, ip)
|
||||
return
|
||||
}
|
||||
|
||||
// SendSms SendSms
|
||||
func (s *Service) SendSms(c context.Context, tdoSendSms model.TdoSendSms) (err error) {
|
||||
err = s.d.SendSms(c, tdoSendSms)
|
||||
return
|
||||
}
|
@ -0,0 +1 @@
|
||||
package service
|
@ -0,0 +1,65 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
// RenewToken renew token.
|
||||
func (s *Service) RenewToken(c context.Context, accessKey, from string) (res *model.RenewToken, err error) {
|
||||
if accessKey == "" {
|
||||
err = ecode.AccessKeyErr
|
||||
return
|
||||
}
|
||||
region, ok := region(accessKey)
|
||||
if !ok {
|
||||
err = ecode.AccessKeyErr
|
||||
return
|
||||
}
|
||||
if region == s.currentRegion {
|
||||
return s.currentRenewToken(c, accessKey)
|
||||
}
|
||||
if region == _origin {
|
||||
if res, err = s.d.RenewToken(context.TODO(), s.renewToken[_origin], accessKey, s.currentRegion); err != nil {
|
||||
return
|
||||
}
|
||||
if _, innerErr := s.currentRenewToken(c, accessKey); innerErr != nil {
|
||||
log.Error("renewtoken succeeded on origin but failed on cloud, accessKey(%s) from(%s) error(%v)", accessKey, from, innerErr)
|
||||
}
|
||||
return
|
||||
}
|
||||
if from != "" {
|
||||
s.dispatcherErrStats.Incr("dispatcher_error")
|
||||
err = ErrDispatcherError
|
||||
return
|
||||
}
|
||||
return s.d.RenewToken(c, s.renewToken[region], accessKey, s.currentRegion)
|
||||
}
|
||||
|
||||
func (s *Service) currentRenewToken(c context.Context, accessKey string) (res *model.RenewToken, err error) {
|
||||
var tokenInfo *model.Perm
|
||||
if tokenInfo, err = s.tokenInfo(c, accessKey); err != nil {
|
||||
return
|
||||
}
|
||||
if tokenInfo == nil {
|
||||
err = ecode.AccessKeyErr
|
||||
return
|
||||
}
|
||||
expires := time.Now().Unix() + _expireSeconds
|
||||
token := &model.Perm{
|
||||
Expires: expires,
|
||||
AccessToken: accessKey,
|
||||
}
|
||||
if _, err = s.d.UpdateToken(c, token); err != nil {
|
||||
return
|
||||
}
|
||||
s.d.DelTokenCache(c, accessKey)
|
||||
res = &model.RenewToken{
|
||||
Expires: expires,
|
||||
}
|
||||
return
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func TestService_RenewToken(t *testing.T) {
|
||||
once.Do(startService)
|
||||
ak := "4de8aecfafc7f91cb650d6371efb1b63"
|
||||
if res, err := s.RenewToken(context.TODO(), ak, ""); err != nil {
|
||||
t.Errorf("s.RenewToken() error(%v)", err)
|
||||
t.FailNow()
|
||||
} else if res == nil || res.Expires == 0 {
|
||||
t.Errorf("res is not correct, expected res with expires non zero but got %v", res)
|
||||
t.FailNow()
|
||||
} else {
|
||||
str, _ := json.Marshal(res)
|
||||
t.Logf("res: %s", str)
|
||||
}
|
||||
}
|
17
app/service/main/passport-game/service/passport_test.go
Normal file
17
app/service/main/passport-game/service/passport_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestServiceApp(t *testing.T) {
|
||||
once.Do(startService)
|
||||
if app, ok := s.appMap[_gameAppKey]; !ok {
|
||||
t.Errorf("res is not correct, expect game app exists but nil")
|
||||
t.FailNow()
|
||||
} else {
|
||||
str, _ := json.Marshal(app)
|
||||
t.Logf("res: %s", str)
|
||||
}
|
||||
}
|
35
app/service/main/passport-game/service/region.go
Normal file
35
app/service/main/passport-game/service/region.go
Normal file
@ -0,0 +1,35 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
)
|
||||
|
||||
const (
|
||||
_segmentation = "_"
|
||||
|
||||
_origin = "origin"
|
||||
)
|
||||
|
||||
// Regions get region list.
|
||||
func (s *Service) Regions(c context.Context) (res []*model.RegionInfo) {
|
||||
return s.regionItems
|
||||
}
|
||||
|
||||
// region returns region for token, use it in ok pattern:
|
||||
// if token end with "_", returns "", false,
|
||||
// if token end with "_foo", then returns "foo", true,
|
||||
// otherwise returns "origin".
|
||||
func region(token string) (string, bool) {
|
||||
index := strings.Index(token, _segmentation)
|
||||
if index < 0 {
|
||||
return _origin, true
|
||||
}
|
||||
suffix := token[index+1:]
|
||||
if suffix == "" {
|
||||
return "", false
|
||||
}
|
||||
return suffix, true
|
||||
}
|
37
app/service/main/passport-game/service/region_test.go
Normal file
37
app/service/main/passport-game/service/region_test.go
Normal file
@ -0,0 +1,37 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestService_Regions(t *testing.T) {
|
||||
once.Do(startService)
|
||||
m := s.Regions(context.TODO())
|
||||
res, _ := json.Marshal(m)
|
||||
t.Logf("res: %s", res)
|
||||
}
|
||||
|
||||
func TestService_Region(t *testing.T) {
|
||||
ak := "4de8aecfafc7f91cb650d6371efb1b63"
|
||||
r, _ := region(ak)
|
||||
if r != _origin {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("ak: %s, region: %s", ak, r)
|
||||
|
||||
ak = "4de8aecfafc7f91cb650d6371efb1b63_t1"
|
||||
r, _ = region(ak)
|
||||
if r != "t1" {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("ak: %s, region: %s", ak, r)
|
||||
|
||||
ak = "4de8aecfafc7f91cb650d6371efb1b63_"
|
||||
_, ok := region(ak)
|
||||
if ok {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("ak: %s, ok: %t", ak, ok)
|
||||
}
|
60
app/service/main/passport-game/service/rsa.go
Normal file
60
app/service/main/passport-game/service/rsa.go
Normal file
@ -0,0 +1,60 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrPublicKeyError public key error
|
||||
ErrPublicKeyError = errors.New("public key error")
|
||||
// ErrPrivateKeyError private key error
|
||||
ErrPrivateKeyError = errors.New("private key error")
|
||||
// ErrUnsupportedPubKey Unsupported key error
|
||||
ErrUnsupportedPubKey = errors.New("unsupported public key")
|
||||
// ErrUnsupportedPrivKey Private key error
|
||||
ErrUnsupportedPrivKey = errors.New("unsupported private key")
|
||||
)
|
||||
|
||||
func pubKey(publicKey []byte) (*rsa.PublicKey, error) {
|
||||
block, _ := pem.Decode(publicKey)
|
||||
if block == nil {
|
||||
return nil, ErrPublicKeyError
|
||||
}
|
||||
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pub, ok := pubInterface.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, ErrUnsupportedPubKey
|
||||
}
|
||||
return pub, nil
|
||||
}
|
||||
|
||||
func privKey(privateKey []byte) (*rsa.PrivateKey, error) {
|
||||
block, _ := pem.Decode(privateKey)
|
||||
if block == nil {
|
||||
return nil, ErrPrivateKeyError
|
||||
}
|
||||
privInterface, err := x509.ParsePKCS8PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv, ok := privInterface.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, ErrUnsupportedPrivKey
|
||||
}
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
func rsaEncryptPKCS8(pub *rsa.PublicKey, origData []byte) ([]byte, error) {
|
||||
return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
|
||||
}
|
||||
|
||||
func rsaDecryptPKCS8(priv *rsa.PrivateKey, ciphertext []byte) ([]byte, error) {
|
||||
return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
|
||||
}
|
65
app/service/main/passport-game/service/rsa_test.go
Normal file
65
app/service/main/passport-game/service/rsa_test.go
Normal file
@ -0,0 +1,65 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDecode(t *testing.T) {
|
||||
s := "Qiu+Iyqi/URq8fbd/FQAtN8CPJ/LT9AAG5/dSd+RSRjH4OgGp3tJMvOk7uqzzgWDi0EYDsLp2xme61NdjhITz1eRmN11oyu2cYqsk9Rqp0o3LzNHeMuUL4GMdWlhRNBQMoNJdzmSaPZoIlgL3vxK+ghg/zF8clqvMSYryuy+rZI="
|
||||
key, err := privKey([]byte(_originPrivKey))
|
||||
fmt.Println(err)
|
||||
d, _ := base64.StdEncoding.DecodeString(s)
|
||||
b, err := rsaDecryptPKCS8(key, d)
|
||||
fmt.Println(err)
|
||||
fmt.Println(string(b))
|
||||
}
|
||||
|
||||
func TestRSADecryptPKCS8(t *testing.T) {
|
||||
plain := []byte("hello")
|
||||
pub, err := pubKey([]byte(_originPubKey))
|
||||
if err != nil {
|
||||
t.Errorf("failed to init pub key, error(%v)", err)
|
||||
t.FailNow()
|
||||
}
|
||||
d, err := rsaEncryptPKCS8(pub, plain)
|
||||
if err != nil {
|
||||
t.Errorf("failed to rsa encrypt, error(%v)", err)
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("d: %s", base64.StdEncoding.EncodeToString(d))
|
||||
priv, err := privKey([]byte(_originPrivKey))
|
||||
if err != nil {
|
||||
t.Errorf("failed to init priv key, error(%v)", err)
|
||||
t.FailNow()
|
||||
}
|
||||
fn := "/tmp/pwd.txt"
|
||||
f, err := os.Open(fn)
|
||||
if err != nil {
|
||||
t.Errorf("failed to open file %s, error(%v)", fn, err)
|
||||
t.FailNow()
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
rd := bufio.NewReader(f)
|
||||
i := 0
|
||||
for {
|
||||
line, err := rd.ReadString('\n')
|
||||
|
||||
if err != nil || io.EOF == err {
|
||||
break
|
||||
}
|
||||
d, _ = base64.StdEncoding.DecodeString(line)
|
||||
p, err := rsaDecryptPKCS8(priv, d)
|
||||
if err != nil {
|
||||
t.Errorf("failed to rsa decrypt, error(%v)", err)
|
||||
t.FailNow()
|
||||
}
|
||||
i++
|
||||
t.Logf("%d: %s\n", i, p[16:])
|
||||
}
|
||||
}
|
118
app/service/main/passport-game/service/rsa_time_hash.go
Normal file
118
app/service/main/passport-game/service/rsa_time_hash.go
Normal file
@ -0,0 +1,118 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
_bits = uint64(4)
|
||||
_splitOn = 32 / _bits
|
||||
)
|
||||
|
||||
var (
|
||||
table = []uint64{
|
||||
0x4f3a97cb, 0x8ae2d379, 0xe8df369a, 0x5ac82647, 0xcdaf6987, 0xabd28536, 0x3e5f2a7b, 0x792e85df,
|
||||
0xeac3d972, 0xca9b7fe5, 0xbdcf5473, 0x895ad732, 0xc9d6b324, 0xd3549a72, 0xde72ab89, 0xf4a6dc53,
|
||||
0x6a8e752b, 0xa736d25f, 0xc3ad8296, 0xb435f689, 0x7fce594b, 0x529ca743, 0x3c4ab2d7, 0x94c8adf6,
|
||||
0x893746c2, 0x6ceda579, 0xcad36b75, 0x6f4a973e, 0xf3a49c56, 0xb645f2d9, 0xd72a56f8, 0x4b3d6fa9,
|
||||
0xd354cf2a, 0x26b4f5d8, 0x3e9f64ad, 0xae4fd326, 0x3f9247d6, 0xe4c67f95, 0xfed8c9b4, 0x249637db,
|
||||
0xdefabc54, 0xa9ebd87c, 0xcf2864ea, 0xf632d475, 0x5e3b6897, 0xed7f94b8, 0x67a4cfd2, 0x97a82e65,
|
||||
0x2369b7a4, 0x2ca3e6d4, 0xc57fba36, 0xdf3e7846, 0xde324ba5, 0x7ec56f24, 0xb598c3af, 0x389fd4ae,
|
||||
0xa3b6472c, 0x2f94a8be, 0x93fcab42, 0x82f34aeb, 0x94e8b372, 0x87c42b9e, 0x2f9b574c, 0x7ec693fa,
|
||||
0x9245fc67, 0x823bf4ce, 0x9357f84d, 0xed529a87, 0xb4625ead, 0xbcd4f6a9, 0x7863ca52, 0xd4762cef,
|
||||
0xe8d6c479, 0xbc46f579, 0xa9486fdc, 0xced6f289, 0xd8a3b629, 0x49fce523, 0x62e8db97, 0xc23bf769,
|
||||
0xa9c64d7f, 0x52dab6f7, 0x965cdf8e, 0xc4872fe9, 0x9764de53, 0x24bef897, 0x5b7a962c, 0x3f8d72be,
|
||||
0xd26fa89c, 0x58bf742e, 0xac3bd967, 0x36cae942, 0x48d3fb9c, 0xa2f59ed3, 0xa6f8379d, 0x29bf46d7,
|
||||
0x8cdbe243, 0x375c4bf9, 0x872f9dc5, 0x87a46ef5, 0x53d48ac9, 0x97e6ca3d, 0x2fec5a3b, 0x597dafe3,
|
||||
0x382ed7a9, 0xbc34d687, 0x869ecbf7, 0x7b38549a, 0x9f28746c, 0x95cb7e83, 0xec85f9a7, 0x2a947c8e,
|
||||
0x7ba689fd, 0xebc24893, 0xa362cf7e, 0xa48e3cb5, 0xe247589d, 0x7c92edaf, 0x84635c2d, 0xad2c6bfe,
|
||||
0xec456daf, 0x2d6e5f47, 0xfa9ce625, 0x7c4a8b62, 0x9cd728f5, 0x3be4a29d, 0xd62a589c, 0x843cb629,
|
||||
0x4ce5b6d3, 0x2fd6a9ce, 0x8d7af3bc, 0x8f37a695, 0xfe935da4, 0x4d8b6ea2, 0xa52dc4e9, 0x8e2a537b,
|
||||
0x7e23456f, 0x6cb8dafe, 0x957bf34d, 0x4ec72ad8, 0xa75c4982, 0x83afb76e, 0xb895fca6, 0x865abd24,
|
||||
0x9ae2475d, 0xf3c45eb8, 0xba4d2ef5, 0xb2da463e, 0xfd392a5e, 0x76a9fd58, 0x3ead48f6, 0x8ea62537,
|
||||
0xd6c35ba2, 0x758d9e24, 0xd524ec93, 0x67bc42a5, 0x354d9f87, 0xe2d3578f, 0xe87452fa, 0x5e439fca,
|
||||
0xd29b37c8, 0x8fe64c3b, 0x4ac5368d, 0x5e8acf9b, 0x6f9c3ad2, 0xaef3827b, 0x5328e46b, 0xbdef7ca9,
|
||||
0x3da592c4, 0x45fe7db2, 0xc9b65a3d, 0x4a578ec3, 0xc46deab9, 0xb3689edc, 0x84aed59f, 0x235b9af7,
|
||||
0xa9b6d48f, 0x6de379bf, 0x2749fa5e, 0x2469a7ef, 0xdf9e62a7, 0xb39a86d2, 0x8539b72c, 0x8dfa9ebc,
|
||||
0xdec397f5, 0xdba3c4e2, 0x9a38e6fd, 0xe98a734f, 0xe94b8d7f, 0x874cd9b3, 0xb75c6ef4, 0x9f56378c,
|
||||
0xc43f2d78, 0x74ea9253, 0x2c5dbef4, 0xbc7e26f9, 0x943b2c6d, 0x25faeb76, 0x53b278de, 0x6eb5948f,
|
||||
0xc4967358, 0x49f63a7e, 0x7a596ec4, 0x948cabf5, 0x945c638e, 0x6fd258b7, 0x697e8b3f, 0x56ab7823,
|
||||
0xc53b6a89, 0xa3bfc579, 0xaec45d36, 0xcdea9b28, 0x9e8f2356, 0xdb694a2e, 0xdf732e8a, 0xec7463d5,
|
||||
0xbf5ec9a8, 0x6dbfa984, 0xc4798e5a, 0x67e9382b, 0xe7ac3249, 0x5e238b9a, 0xbd632eaf, 0xaf92b685,
|
||||
0x6bcae435, 0x97236fd8, 0x37fcbea4, 0x5fe9da23, 0xb593a4f7, 0x3e27d84c, 0xa5db932f, 0x8c6274de,
|
||||
0xca54bd72, 0x63f42ed5, 0x6ad37285, 0xbd4fe7c9, 0x5f49a6b3, 0x38b592ec, 0x273d456b, 0x4e9253b7,
|
||||
0xf2da9b8c, 0xb85c642d, 0x3d7489ca, 0x7426fe3b, 0x4bce6ad2, 0x3276becd, 0x96f43bec, 0xf296dba4,
|
||||
0x3ebc8d72, 0xf593b4ca, 0x2a63547f, 0xa5bcd87e, 0x39fd25ae, 0xce6f4b38, 0xf36cd978, 0x62e94a37,
|
||||
}
|
||||
)
|
||||
|
||||
// TsSeconds2Hash generate hash from seconds ts.
|
||||
func TsSeconds2Hash(tsSecond int64) string {
|
||||
hashSeedMills := time.Now().UnixNano() / time.Millisecond.Nanoseconds()
|
||||
randomIndex := rand.Intn(255)
|
||||
hashVal := md5Hex(strconv.FormatInt(hashSeedMills, 10))
|
||||
hashVal = hashVal[:16]
|
||||
ris := fmt.Sprintf("%02x", randomIndex)
|
||||
hashVal = replaceStr(hashVal, ris, 0)
|
||||
val := table[randomIndex]
|
||||
ts := fmt.Sprintf("%08x", tsSecond)
|
||||
poses := decompress(val)
|
||||
for i, pos := range poses {
|
||||
s := ts[i : i+1]
|
||||
hashVal = replaceStr(hashVal, s, int(pos))
|
||||
}
|
||||
return hashVal
|
||||
}
|
||||
|
||||
func replaceStr(origin, s string, pos int) string {
|
||||
if pos > 0 {
|
||||
return origin[:pos] + s + origin[pos+len(s):]
|
||||
}
|
||||
return s + origin[pos+len(s):]
|
||||
}
|
||||
|
||||
func decompress(mixed uint64) []uint64 {
|
||||
filterVal := uint64((1 << _bits) - 1)
|
||||
val := make([]uint64, _splitOn)
|
||||
itemNums := _splitOn
|
||||
mixedArr := []uint64{mixed}
|
||||
n := uint64(0)
|
||||
for _, sval := range mixedArr {
|
||||
for k := uint64(0); k < _splitOn; k++ {
|
||||
var dval uint64
|
||||
if k == 0 {
|
||||
dval = sval & filterVal
|
||||
} else {
|
||||
dval = (sval >> (_bits * k)) & filterVal
|
||||
}
|
||||
val[k] = dval
|
||||
n++
|
||||
if n == itemNums {
|
||||
break
|
||||
}
|
||||
}
|
||||
if n == itemNums {
|
||||
break
|
||||
}
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// Hash2TsSeconds parse ts seconds from hash.
|
||||
func Hash2TsSeconds(timeHash string) (ts int64, err error) {
|
||||
randomIndex, err := strconv.ParseInt(timeHash[0:2], 16, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
val := table[randomIndex]
|
||||
poses := decompress(val)
|
||||
tsStr := ""
|
||||
for _, pos := range poses {
|
||||
tsStr = tsStr + timeHash[pos:pos+1]
|
||||
}
|
||||
ts, err = strconv.ParseInt(tsStr, 16, 64)
|
||||
return
|
||||
}
|
38
app/service/main/passport-game/service/rsa_time_hash_test.go
Normal file
38
app/service/main/passport-game/service/rsa_time_hash_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func BenchmarkTsSecond2Hash(b *testing.B) {
|
||||
ts := time.Now().Unix()
|
||||
for i := 0; i < b.N; i++ {
|
||||
ts += int64(rand.Intn(100))
|
||||
hash := TsSeconds2Hash(ts)
|
||||
if ats, err := Hash2TsSeconds(hash); err != nil {
|
||||
b.Errorf("failed to parse hash, error(%v)", err)
|
||||
b.FailNow()
|
||||
} else if ats != ts {
|
||||
b.Errorf("hash: %s, expect %d but got %d", hash, ts, ats)
|
||||
b.FailNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecompress(t *testing.T) {
|
||||
val := table[5] // 0xabd28536
|
||||
exp := []uint64{6, 3, 5, 8, 2, 13, 11, 10}
|
||||
poses := decompress(val)
|
||||
if len(poses) != len(exp) {
|
||||
t.Errorf("res is not correct, expected poses length equal to exp length, but not, poses length: %d, exp length: %d", len(poses), len(exp))
|
||||
t.FailNow()
|
||||
}
|
||||
for i, item := range exp {
|
||||
if poses[i] != item {
|
||||
t.Errorf("failed to decompress, expected %v but got %v", exp, poses)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
}
|
124
app/service/main/passport-game/service/service.go
Normal file
124
app/service/main/passport-game/service/service.go
Normal file
@ -0,0 +1,124 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rsa"
|
||||
|
||||
"go-common/app/service/main/passport-game/conf"
|
||||
"go-common/app/service/main/passport-game/dao"
|
||||
"go-common/app/service/main/passport-game/model"
|
||||
"go-common/library/log"
|
||||
"go-common/library/stat"
|
||||
"go-common/library/stat/prom"
|
||||
)
|
||||
|
||||
// Service service.
|
||||
type Service struct {
|
||||
c *conf.Config
|
||||
d *dao.Dao
|
||||
missch chan func()
|
||||
appMap map[string]*model.App
|
||||
originPubKey *rsa.PublicKey
|
||||
cloudRSAKey *RSAKey
|
||||
proxy bool
|
||||
currentRegion string
|
||||
oauth map[string]string
|
||||
renewToken map[string]string
|
||||
regionItems []*model.RegionInfo
|
||||
dispatcherErrStats stat.Stat
|
||||
}
|
||||
|
||||
// RSAKey RSA public and private key.
|
||||
type RSAKey struct {
|
||||
pub *rsa.PublicKey
|
||||
priv *rsa.PrivateKey
|
||||
}
|
||||
|
||||
// New new a service instance.
|
||||
func New(c *conf.Config) (s *Service) {
|
||||
d := dao.New(c)
|
||||
// load apps
|
||||
apps, err := d.Apps(context.TODO())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(apps) == 0 {
|
||||
panic("apps loaded from db is empty, abort")
|
||||
}
|
||||
appMap := make(map[string]*model.App, len(apps))
|
||||
for _, app := range apps {
|
||||
appMap[app.AppKey] = app
|
||||
}
|
||||
// load origin public key
|
||||
key, err := d.RSAKeyOrigin(context.TODO())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
originPub, err := pubKey([]byte(key.Key))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// load origin public and private key for cloud
|
||||
pub, err := pubKey([]byte(_originPubKey))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
priv, err := privKey([]byte(_originPrivKey))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// init
|
||||
s = &Service{
|
||||
c: c,
|
||||
d: d,
|
||||
missch: make(chan func(), 10240),
|
||||
appMap: appMap,
|
||||
originPubKey: originPub,
|
||||
cloudRSAKey: &RSAKey{
|
||||
pub: pub,
|
||||
priv: priv,
|
||||
},
|
||||
proxy: c.Proxy,
|
||||
currentRegion: c.Dispatcher.Name,
|
||||
oauth: c.Dispatcher.Oauth,
|
||||
renewToken: c.Dispatcher.RenewToken,
|
||||
regionItems: c.Dispatcher.RegionInfos,
|
||||
dispatcherErrStats: prom.BusinessErrCount,
|
||||
}
|
||||
go s.cacheproc()
|
||||
return
|
||||
}
|
||||
|
||||
// APP query appkey
|
||||
func (s *Service) APP(app string) (v *model.App, ok bool) {
|
||||
v, ok = s.appMap[app]
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) addCache(f func()) {
|
||||
select {
|
||||
case s.missch <- f:
|
||||
default:
|
||||
log.Warn("cache chan full")
|
||||
}
|
||||
}
|
||||
|
||||
// cacheproc is a routine for executing closure.
|
||||
func (s *Service) cacheproc() {
|
||||
for {
|
||||
f := <-s.missch
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
// Ping check server ok.
|
||||
func (s *Service) Ping(c context.Context) (err error) {
|
||||
err = s.d.Ping(c)
|
||||
return
|
||||
}
|
||||
|
||||
// Close close service, including closing dao.
|
||||
func (s *Service) Close() (err error) {
|
||||
s.d.Close()
|
||||
return
|
||||
}
|
31
app/service/main/passport-game/service/service_test.go
Normal file
31
app/service/main/passport-game/service/service_test.go
Normal file
@ -0,0 +1,31 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"go-common/app/service/main/passport-game/conf"
|
||||
)
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
s *Service
|
||||
)
|
||||
|
||||
func startService() {
|
||||
if err := conf.Init(); err != nil {
|
||||
panic(fmt.Sprintf("conf.Init() error(%v)", err))
|
||||
}
|
||||
s = New(conf.Conf)
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
once.Do(startService)
|
||||
if s.c.AccountURI == "" || s.c.PassportURI == "" {
|
||||
t.Errorf("conf is not correct, expected account URI and passport URI not empty but not, account URI: %s, passport URI: %s", s.c.AccountURI, s.c.PassportURI)
|
||||
t.FailNow()
|
||||
} else {
|
||||
t.Logf("s.c.AccountURI: %s, s.c.PassportURI: %s", s.c.AccountURI, s.c.PassportURI)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user