Create & Init Project...

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

View File

@@ -0,0 +1,22 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/main/passport-sns/api:all-srcs",
"//app/service/main/passport-sns/cmd:all-srcs",
"//app/service/main/passport-sns/conf:all-srcs",
"//app/service/main/passport-sns/dao:all-srcs",
"//app/service/main/passport-sns/model:all-srcs",
"//app/service/main/passport-sns/server/http:all-srcs",
"//app/service/main/passport-sns/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,2 @@
# v1.0.0
1. init

View File

@@ -0,0 +1,10 @@
# Owner
wutao
wanghuan01
# Author
chenjunxi
# Reviewer
wutao
wanghuan01

View File

@@ -0,0 +1,19 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- chenjunxi
- wanghuan01
- wutao
- zhaoyixuan
- zhoujiahui
labels:
- main
- service
- service/main/passport-sns
options:
no_parent_owners: true
reviewers:
- chenjunxi
- wanghuan01
- wutao
- zhoujiahui

View File

@@ -0,0 +1,12 @@
# passport-sns-service
# 项目简介
1.
# 编译环境
# 依赖包
# 编译执行

View File

@@ -0,0 +1,65 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
proto_library(
name = "api_proto",
srcs = ["api.proto"],
tags = ["automanaged"],
deps = [
"@go_googleapis//google/api:annotations_proto",
"@gogo_special_proto//github.com/gogo/protobuf/gogoproto",
],
)
go_proto_library(
name = "api_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_grpc"],
importpath = "go-common/app/service/main/passport-sns/api",
proto = ":api_proto",
tags = ["automanaged"],
deps = [
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@go_googleapis//google/api:annotations_go_proto",
],
)
go_library(
name = "go_default_library",
srcs = ["api.bm.go"],
embed = [":api_go_proto"],
importpath = "go-common/app/service/main/passport-sns/api",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/binding:go_default_library",
"//vendor/google.golang.org/genproto/googleapis/api/annotations:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_x_net//context:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,133 @@
// Code generated by protoc-gen-bm v0.1, DO NOT EDIT.
// source: api.proto
/*
Package api is a generated blademaster stub package.
This code was generated with go-common/app/tool/bmgen/protoc-gen-bm v0.1.
It is generated from these files:
api.proto
*/
package api
import (
"context"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
// to suppressed 'imported but not used warning'
var _ *bm.Context
var _ context.Context
var _ binding.StructValidator
var PathPassportSNSGetAuthorizeURL = "/x/internal/passport-sns/authorize/url"
var PathPassportSNSBind = "/x/internal/passport-sns/bind"
var PathPassportSNSUnbind = "/x/internal/passport-sns/unbind"
var PathPassportSNSGetInfo = "/x/internal/passport-sns/info"
var PathPassportSNSGetInfoByCode = "/x/internal/passport-sns/info/code"
var PathPassportSNSUpdateInfo = "/x/internal/passport-sns/info/update"
// =====================
// PassportSNS Interface
// =====================
type PassportSNSBMServer interface {
// GetAuthorizeURL get authorize url
GetAuthorizeURL(ctx context.Context, req *GetAuthorizeURLReq) (resp *GetAuthorizeURLReply, err error)
// Bind bind sns account
Bind(ctx context.Context, req *BindReq) (resp *EmptyReply, err error)
// Unbind unbind sns account
Unbind(ctx context.Context, req *UnbindReq) (resp *EmptyReply, err error)
// GetInfo get info by mid
GetInfo(ctx context.Context, req *GetInfoReq) (resp *GetInfoReply, err error)
// GetInfoByCode get info by authorize code
GetInfoByCode(ctx context.Context, req *GetInfoByCodeReq) (resp *GetInfoByCodeReply, err error)
// UpdateInfo update info
UpdateInfo(ctx context.Context, req *UpdateInfoReq) (resp *EmptyReply, err error)
}
var PassportSNSSvc PassportSNSBMServer
func passportSNSGetAuthorizeURL(c *bm.Context) {
p := new(GetAuthorizeURLReq)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := PassportSNSSvc.GetAuthorizeURL(c, p)
c.JSON(resp, err)
}
func passportSNSBind(c *bm.Context) {
p := new(BindReq)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := PassportSNSSvc.Bind(c, p)
c.JSON(resp, err)
}
func passportSNSUnbind(c *bm.Context) {
p := new(UnbindReq)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := PassportSNSSvc.Unbind(c, p)
c.JSON(resp, err)
}
func passportSNSGetInfo(c *bm.Context) {
p := new(GetInfoReq)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := PassportSNSSvc.GetInfo(c, p)
c.JSON(resp, err)
}
func passportSNSGetInfoByCode(c *bm.Context) {
p := new(GetInfoByCodeReq)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := PassportSNSSvc.GetInfoByCode(c, p)
c.JSON(resp, err)
}
func passportSNSUpdateInfo(c *bm.Context) {
p := new(UpdateInfoReq)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := PassportSNSSvc.UpdateInfo(c, p)
c.JSON(resp, err)
}
// RegisterPassportSNSService Register the blademaster route with middleware map
// midMap is the middleware map, the key is defined in proto
func RegisterPassportSNSService(e *bm.Engine, svc PassportSNSBMServer, midMap map[string]bm.HandlerFunc) {
PassportSNSSvc = svc
e.GET("/x/internal/passport-sns/authorize/url", passportSNSGetAuthorizeURL)
e.POST("/x/internal/passport-sns/bind", passportSNSBind)
e.POST("/x/internal/passport-sns/unbind", passportSNSUnbind)
e.GET("/x/internal/passport-sns/info", passportSNSGetInfo)
e.GET("/x/internal/passport-sns/info/code", passportSNSGetInfoByCode)
e.POST("/x/internal/passport-sns/info/update", passportSNSUpdateInfo)
}
// RegisterPassportSNSBMServer Register the blademaster route
func RegisterPassportSNSBMServer(e *bm.Engine, server PassportSNSBMServer) {
PassportSNSSvc = server
e.GET("/x/internal/passport-sns/authorize/url", passportSNSGetAuthorizeURL)
e.POST("/x/internal/passport-sns/bind", passportSNSBind)
e.POST("/x/internal/passport-sns/unbind", passportSNSUnbind)
e.GET("/x/internal/passport-sns/info", passportSNSGetInfo)
e.GET("/x/internal/passport-sns/info/code", passportSNSGetInfoByCode)
e.POST("/x/internal/passport-sns/info/update", passportSNSUpdateInfo)
}

View File

@@ -0,0 +1,174 @@
<!-- package=passport.service.sns -->
- [/x/internal/passport-sns/authorize/url](#xinternalpassport-snsauthorizeurl) GetAuthorizeURL get authorize url
- [/x/internal/passport-sns/bind](#xinternalpassport-snsbind) Bind bind sns account
- [/x/internal/passport-sns/unbind](#xinternalpassport-snsunbind) Unbind unbind sns account
- [/x/internal/passport-sns/info](#xinternalpassport-snsinfo) GetInfo get info by mid
- [/x/internal/passport-sns/info/code](#xinternalpassport-snsinfocode) GetInfoByCode get info by authorize code
- [/x/internal/passport-sns/info/update](#xinternalpassport-snsinfoupdate) UpdateInfo update info
## /x/internal/passport-sns/authorize/url
### GetAuthorizeURL get authorize url
#### 方法GET
#### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|app_id|是|string||
|platform|是|string||
|redirect_url|是|string||
|display|否|string||
#### 响应
```javascript
{
"code": 0,
"message": "ok",
"data": {
"url": ""
}
}
```
## /x/internal/passport-sns/bind
### Bind bind sns account
#### 方法POST
#### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|mid|是|integer||
|code|是|string||
|app_id|是|string||
|platform|是|string||
|redirect_url|是|string||
#### 响应
```javascript
{
"code": 0,
"message": "ok",
"data": {
}
}
```
## /x/internal/passport-sns/unbind
### Unbind unbind sns account
#### 方法POST
#### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|mid|是|integer||
|app_id|否|string||
|platform|是|string||
#### 响应
```javascript
{
"code": 0,
"message": "ok",
"data": {
}
}
```
## /x/internal/passport-sns/info
### GetInfo get info by mid
#### 方法GET
#### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|mid|是|integer||
#### 响应
```javascript
{
"code": 0,
"message": "ok",
"data": {
"infos": [
{
"mid": 0,
"platform": "",
"unionid": "",
"expires": 0
}
]
}
}
```
## /x/internal/passport-sns/info/code
### GetInfoByCode get info by authorize code
#### 方法GET
#### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|code|是|string||
|app_id|是|string||
|platform|是|string||
|redirect_url|是|string||
#### 响应
```javascript
{
"code": 0,
"message": "ok",
"data": {
"mid": 0,
"unionid": "",
"openid": "",
"expires": 0,
"token": ""
}
}
```
## /x/internal/passport-sns/info/update
### UpdateInfo update info
#### 方法POST
#### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|platform|是|string||
|app_id|是|string||
|mid|是|integer||
|open_id|是|string||
#### 响应
```javascript
{
"code": 0,
"message": "ok",
"data": {
}
}
```

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,112 @@
syntax = "proto3";
import "google/api/annotations.proto";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
package passport.service.sns;
option go_package = "api";
service PassportSNS {
// GetAuthorizeURL get authorize url
rpc GetAuthorizeURL (GetAuthorizeURLReq) returns (GetAuthorizeURLReply) {
option (google.api.http) = {
get: "/x/internal/passport-sns/authorize/url";
};
}
// Bind bind sns account
rpc Bind (BindReq) returns (EmptyReply) {
option (google.api.http) = {
post: "/x/internal/passport-sns/bind";
};
}
// Unbind unbind sns account
rpc Unbind (UnbindReq) returns (EmptyReply) {
option (google.api.http) = {
post: "/x/internal/passport-sns/unbind";
};
}
// GetInfo get info by mid
rpc GetInfo (GetInfoReq) returns (GetInfoReply) {
option (google.api.http) = {
get: "/x/internal/passport-sns/info";
};
}
// GetInfoByCode get info by authorize code
rpc GetInfoByCode (GetInfoByCodeReq) returns (GetInfoByCodeReply) {
option (google.api.http) = {
get: "/x/internal/passport-sns/info/code";
};
}
// UpdateInfo update info
rpc UpdateInfo (UpdateInfoReq) returns (EmptyReply) {
option (google.api.http) = {
post: "/x/internal/passport-sns/info/update";
};
}
}
message EmptyReply {
}
message Info {
int64 mid = 1 [(gogoproto.jsontag) = "mid"];
string platform = 2 [(gogoproto.jsontag) = "platform"];
string union_id = 3 [(gogoproto.jsontag) = "unionid"];
int64 expires = 4 [(gogoproto.jsontag) = "expires"];
}
message GetAuthorizeURLReq {
string app_id = 1 [(gogoproto.moretags) = "form:\"appid\" validate:\"required\""];
string platform = 2 [(gogoproto.moretags) = "form:\"platform\" validate:\"required\""];
string redirect_url = 3 [(gogoproto.moretags) = "form:\"redirect_url\" validate:\"required\""];
string display = 4 [(gogoproto.moretags) = "form:\"display\""];
}
message GetAuthorizeURLReply {
string url = 1 [(gogoproto.jsontag) = "url"];
}
message BindReq {
int64 mid = 1 [(gogoproto.moretags) = "form:\"mid\" validate:\"required\""];
string code = 2 [(gogoproto.moretags) = "form:\"code\" validate:\"required\""];
string app_id = 3 [(gogoproto.moretags) = "form:\"appid\" validate:\"required\""];
string platform = 4 [(gogoproto.moretags) = "form:\"platform\" validate:\"required\""];
string redirect_url = 5 [(gogoproto.moretags) = "form:\"redirect_url\" validate:\"required\""];
}
message UnbindReq {
int64 mid = 1 [(gogoproto.moretags) = "form:\"mid\" validate:\"required\""];
string app_id = 2 [(gogoproto.moretags) = "form:\"appid\""];
string platform = 3 [(gogoproto.moretags) = "form:\"platform\" validate:\"required\""];
}
message GetInfoReq {
int64 mid = 1 [(gogoproto.moretags) = "form:\"mid\" validate:\"required\""];
}
message GetInfoReply {
repeated Info infos = 1 [(gogoproto.jsontag) = "infos"];
}
message GetInfoByCodeReq {
string code = 1 [(gogoproto.moretags) = "form:\"code\" validate:\"required\""];
string app_id = 2 [(gogoproto.moretags) = "form:\"appid\" validate:\"required\""];
string platform = 3 [(gogoproto.moretags) = "form:\"platform\" validate:\"required\""];
string redirect_url = 4 [(gogoproto.moretags) = "form:\"redirect_url\" validate:\"required\""];
}
message GetInfoByCodeReply {
int64 mid = 1 [(gogoproto.jsontag) = "mid"];
string union_id = 2 [(gogoproto.jsontag) = "unionid"];
string open_id = 3 [(gogoproto.jsontag) = "openid"];
int64 expires = 4 [(gogoproto.jsontag) = "expires"];
string token = 5 [(gogoproto.jsontag) = "token"];
}
message UpdateInfoReq {
string platform = 1 [(gogoproto.moretags) = "form:\"platform\" validate:\"required\""];
string app_id = 2 [(gogoproto.moretags) = "form:\"appid\" validate:\"required\""];
int64 mid = 3 [(gogoproto.moretags) = "form:\"mid\" validate:\"required\""];
string open_id = 4 [(gogoproto.moretags) = "form:\"openid\" validate:\"required\""];
}

View File

@@ -0,0 +1,40 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = ["passport-sns-service.toml"],
importpath = "go-common/app/service/main/passport-sns/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/passport-sns/conf:go_default_library",
"//app/service/main/passport-sns/server/http:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,42 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/service/main/passport-sns/conf"
"go-common/app/service/main/passport-sns/server/http"
"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.Log)
defer log.Close()
log.Info("passport-sns-service start")
trace.Init(conf.Conf.Tracer)
defer trace.Close()
http.Init(conf.Conf)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
log.Info("passport-sns-service exit")
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,47 @@
[log]
stdout = true
[mysql]
addr = "127.0.0.1:3306"
dsn = "root:root@tcp(127.0.0.1:3306)/passport_sns?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
queryTimeout = "1s"
execTimeout = "2s"
tranTimeout = "2s"
[db.user.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[databus.snsLogPub]
key = "4ba46ba31f9a44ef"
secret = "99985eb4451cfb1b899ca0fbe3c4bdc8"
group = "PassportSnslog-MainAccount-P"
topic = "PassportSnslog-T"
action = "pub"
offset = "old"
buffer = 2048
name = "passport-sns/databus"
proto = "tcp"
addr = "172.16.38.154:6205"
idle = 1
active = 1
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
[memcache]
name = "passport-sns-service"
proto = "tcp"
addr = "172.22.33.137:11219"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"

View File

@@ -0,0 +1,40 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/service/main/passport-sns/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//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/http/blademaster/middleware/verify:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/BurntSushi/toml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,99 @@
package conf
import (
"errors"
"flag"
"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/http/blademaster/middleware/verify"
"go-common/library/net/trace"
"go-common/library/queue/databus"
xtime "go-common/library/time"
"github.com/BurntSushi/toml"
)
var (
confPath string
client *conf.Client
// Conf config
Conf = &Config{}
)
// Config .
type Config struct {
Log *log.Config
BM *bm.ServerConfig
Verify *verify.Config
Tracer *trace.Config
MySQL *sql.Config
Memcache *Memcache
//Databus databus
DataBus *DataBus
}
// DataBus databus.
type DataBus struct {
SnsLogPub *databus.Config
}
// Memcache memcache
type Memcache struct {
*memcache.Config
Expire xtime.Duration
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init init conf
func Init() error {
if confPath != "" {
return local()
}
return remote()
}
func local() (err error) {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
if err = load(); err != nil {
return
}
go func() {
for range client.Event() {
log.Info("config reload")
if load() != nil {
log.Error("config reload error (%v)", err)
}
}
}()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Toml2(); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config")
}
*Conf = *tmpConf
return
}

View File

@@ -0,0 +1,64 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"mc_test.go",
"qq_test.go",
"sns_test.go",
"weibo_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/passport-sns/conf:go_default_library",
"//app/service/main/passport-sns/model:go_default_library",
"//library/database/sql:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"mc.go",
"qq.go",
"sns.go",
"weibo.go",
],
importpath = "go-common/app/service/main/passport-sns/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/passport-sns/conf:go_default_library",
"//app/service/main/passport-sns/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",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,51 @@
package dao
import (
"context"
"net/http"
"time"
"go-common/app/service/main/passport-sns/conf"
"go-common/library/cache/memcache"
"go-common/library/database/sql"
)
// Dao dao struct
type Dao struct {
c *conf.Config
db *sql.DB
mc *memcache.Pool
client *http.Client
mcExpire int32
}
// New create new dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: sql.NewMySQL(c.MySQL),
mc: memcache.NewPool(c.Memcache.Config),
mcExpire: int32(time.Duration(c.Memcache.Expire) / time.Second),
client: &http.Client{
Timeout: 600 * time.Millisecond,
},
}
return
}
// Ping check db and mc health.
func (d *Dao) Ping(c context.Context) (err error) {
return
}
// Close close connections of mc, redis, db.
func (d *Dao) Close() {
if d.db != nil {
d.db.Close()
}
}
// BeginTran begin transcation.
func (d *Dao) BeginTran(c context.Context) (tx *sql.Tx, err error) {
return d.db.Begin(c)
}

View File

@@ -0,0 +1,77 @@
package dao
import (
"context"
"flag"
"os"
"reflect"
"testing"
"go-common/app/service/main/passport-sns/conf"
"go-common/library/database/sql"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.passport.passport-sns-service")
flag.Set("conf_token", "f0a341c60edec0e51fd0fbb731c00b39")
flag.Set("tree_id", "80847")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../cmd/passport-sns-service.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}
func TestDaoPing(t *testing.T) {
var c = context.Background()
convey.Convey("Ping", t, func(ctx convey.C) {
err := d.Ping(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoClose(t *testing.T) {
convey.Convey("Close", t, func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Close", func(_ *sql.DB) error {
return nil
})
defer monkey.UnpatchAll()
var err error
d.Close()
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoBeginTran(t *testing.T) {
var c = context.Background()
convey.Convey("BeginTran", t, func(ctx convey.C) {
res, err := d.BeginTran(c)
ctx.Convey("Then err should be nil. res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,114 @@
package dao
import (
"context"
"fmt"
"go-common/app/service/main/passport-sns/model"
"go-common/library/cache/memcache"
"go-common/library/log"
)
func snsKey(platform string, mid int64) string {
return fmt.Sprintf("sns_%s_%d", platform, mid)
}
func oauth2Key(platform string, openID string) string {
return fmt.Sprintf("sns_oauth2_%s_%s", platform, openID)
}
// SetSnsCache set sns to cache
func (d *Dao) SetSnsCache(c context.Context, mid int64, platform string, sns *model.SnsProto) (err error) {
key := snsKey(platform, mid)
conn := d.mc.Get(c)
defer conn.Close()
item := &memcache.Item{Key: key, Object: sns, Flags: memcache.FlagProtobuf, Expiration: d.mcExpire}
if err = conn.Set(item); err != nil {
log.Error("fail to set sns to mc, key(%s) expire(%d) error(%+v)", key, d.mcExpire, err)
}
return
}
// SetOauth2Cache set oauth2 info to cache
func (d *Dao) SetOauth2Cache(c context.Context, openID, platform string, sns *model.Oauth2Proto) (err error) {
key := oauth2Key(platform, openID)
conn := d.mc.Get(c)
defer conn.Close()
item := &memcache.Item{Key: key, Object: sns, Flags: memcache.FlagProtobuf, Expiration: 300}
if err = conn.Set(item); err != nil {
log.Error("fail to set oauth2 info to mc, key(%s) expire(%d) error(%+v)", key, 300, err)
}
return
}
// SnsCache sns cache
func (d *Dao) SnsCache(c context.Context, mid int64, platform string) (res *model.SnsProto, err error) {
key := snsKey(platform, mid)
conn := d.mc.Get(c)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
return nil, nil
}
log.Error("conn.Get(%s) error(%v)", key, err)
return nil, err
}
res = new(model.SnsProto)
if err = conn.Scan(item, res); err != nil {
log.Error("conn.Scan(%s) error(%v)", string(item.Value), err)
return nil, err
}
return res, nil
}
// Oauth2Cache oauth2 info cache
func (d *Dao) Oauth2Cache(c context.Context, openID, platform string) (res *model.Oauth2Proto, err error) {
key := oauth2Key(platform, openID)
conn := d.mc.Get(c)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
return nil, nil
}
log.Error("conn.Get(%s) error(%v)", key, err)
return nil, err
}
res = new(model.Oauth2Proto)
if err = conn.Scan(item, res); err != nil {
log.Error("conn.Scan(%s) error(%v)", string(item.Value), err)
return nil, err
}
return res, nil
}
// DelSnsCache del sns cache
func (d *Dao) DelSnsCache(c context.Context, mid int64, platform string) (err error) {
key := snsKey(platform, mid)
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("fail to del sns cache, key(%s) error(%+v)", key, err)
}
return
}
// DelOauth2Cache del oauth2 cache
func (d *Dao) DelOauth2Cache(c context.Context, openID, platform string) (err error) {
key := oauth2Key(platform, openID)
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("fail to del oauth2 cache, key(%s) error(%+v)", key, err)
}
return
}

View File

@@ -0,0 +1,152 @@
package dao
import (
"context"
"testing"
"go-common/app/service/main/passport-sns/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDao_snsKey(t *testing.T) {
convey.Convey("snsKey", t, func(ctx convey.C) {
var (
platform = model.PlatformQQStr
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res := snsKey(platform, mid)
ctx.Convey("Then res should not be nil.", func(ctx convey.C) {
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDao_oauth2Key(t *testing.T) {
convey.Convey("oauth2Key", t, func(ctx convey.C) {
var (
platform = model.PlatformQQStr
openID = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res := oauth2Key(platform, openID)
ctx.Convey("Then res should not be nil.", func(ctx convey.C) {
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDao_SetSnsCache(t *testing.T) {
convey.Convey("SetSnsCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
platform = model.PlatformQQStr
qq = &model.SnsProto{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.SetSnsCache(c, mid, platform, qq)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDao_SetOauth2Cache(t *testing.T) {
convey.Convey("SetOauth2Cache", t, func(ctx convey.C) {
var (
c = context.Background()
openID = ""
platform = model.PlatformQQStr
qq = &model.Oauth2Proto{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.SetOauth2Cache(c, openID, platform, qq)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDao_SnsCache(t *testing.T) {
convey.Convey("SnsCache", t, func(ctx convey.C) {
var (
c = context.Background()
platform = model.PlatformQQStr
mid = int64(0)
midNotExist = int64(-1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
info, err := d.SnsCache(c, mid, platform)
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)
})
info2, err2 := d.SnsCache(c, midNotExist, platform)
ctx.Convey("Then err should be nil.info should be nil.", func(ctx convey.C) {
ctx.So(err2, convey.ShouldBeNil)
ctx.So(info2, convey.ShouldBeNil)
})
})
})
}
func TestDao_Oauth2Cache(t *testing.T) {
convey.Convey("Oauth2Cache", t, func(ctx convey.C) {
var (
c = context.Background()
openID = ""
openIDNotExist = "-1"
platform = model.PlatformQQStr
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
info, err := d.Oauth2Cache(c, openID, platform)
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)
})
info2, err2 := d.Oauth2Cache(c, openIDNotExist, platform)
ctx.Convey("Then err should be nil.info should be nil.", func(ctx convey.C) {
ctx.So(err2, convey.ShouldBeNil)
ctx.So(info2, convey.ShouldBeNil)
})
})
})
}
func TestDao_DelSnsCache(t *testing.T) {
convey.Convey("DelSnsCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
platform = model.PlatformQQStr
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.DelSnsCache(c, mid, platform)
ctx.Convey("Then err should be nil.info should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDao_DelOauth2Cache(t *testing.T) {
convey.Convey("DelOauth2Cache", t, func(ctx convey.C) {
var (
c = context.Background()
openID = ""
platform = model.PlatformQQStr
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.DelOauth2Cache(c, openID, platform)
ctx.Convey("Then err should be nil.info should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,148 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"go-common/app/service/main/passport-sns/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_qqAuthorizeUrl = "https://graph.qq.com/oauth2.0/authorize"
_qqAccessTokenUrl = "https://graph.qq.com/oauth2.0/token"
_qqOpenIDUrl = "https://graph.qq.com/oauth2.0/me"
_respCodeSuccess = 0
)
// QQAuthorize .
func (d *Dao) QQAuthorize(c context.Context, appID, redirectURL, display string) (url string) {
scope := "do_like,get_user_info,get_simple_userinfo,get_vip_info,get_vip_rich_info,add_one_blog,list_album,upload_pic,add_album,list_photo,get_info,add_t,del_t,add_pic_t,get_repost_list,get_other_info,get_fanslist,get_idollist,add_idol,del_idol,get_tenpay_addr"
displayParam := ""
if display != "" {
displayParam = "&display=" + display
}
return fmt.Sprintf(_qqAuthorizeUrl+"?response_type=code&state=authorize%s&client_id=%s&redirect_uri=%s&scope=%s", displayParam, appID, redirectURL, scope)
}
// QQOauth2Info .
func (d *Dao) QQOauth2Info(c context.Context, code, redirectUrl string, app *model.SnsApps) (res *model.Oauth2Info, err error) {
accessResp, err := d.qqAccessToken(c, code, app.AppID, app.AppSecret, redirectUrl)
if err != nil {
return nil, err
}
openIdResp, err := d.qqOpenID(c, accessResp.Token, app.Business)
if err != nil {
return nil, err
}
// TODO 保证能获取到UnionID的情况可以考虑去掉
if openIdResp.UnionID == "" {
openIdResp.UnionID = openIdResp.OpenID
}
res = &model.Oauth2Info{
UnionID: openIdResp.UnionID,
OpenID: openIdResp.OpenID,
Token: accessResp.Token,
Refresh: accessResp.Refresh,
Expires: accessResp.Expires,
}
return
}
// qqAccessToken .
func (d *Dao) qqAccessToken(c context.Context, code, appID, appSecret, redirectUrl string) (resp *model.QQAccessResp, err error) {
var (
res *http.Response
bs []byte
params = url.Values{}
value = url.Values{}
expires int64
)
params.Set("client_id", appID)
params.Set("client_secret", appSecret)
params.Set("grant_type", "authorization_code")
params.Set("code", code)
params.Set("redirect_uri", redirectUrl)
if res, err = d.client.Get(_qqAccessTokenUrl + "?" + params.Encode()); err != nil {
log.Error("d.qqAccessToken error(%+v) code(%s) appID(%s)", err, code, appID)
return nil, err
}
defer res.Body.Close()
if bs, err = ioutil.ReadAll(res.Body); err != nil {
log.Error("ioutil.ReadAll() error(%+v) code(%s) appID(%s)", err, code, appID)
return nil, err
}
respStr := string(bs)
if strings.HasPrefix(respStr, "callback") {
resp = new(model.QQAccessResp)
start := strings.Index(respStr, "{")
end := strings.Index(respStr, "}")
respStr = respStr[start : end+1]
if err = json.Unmarshal([]byte(respStr), resp); err != nil {
return nil, err
}
log.Error("request qq token failed with code(%d) desc(%s)", resp.Code, resp.Description)
return nil, ecode.PassportSnsRequestErr
}
value, err = url.ParseQuery(respStr)
expires, err = strconv.ParseInt(value.Get("expires_in"), 10, 64)
resp = &model.QQAccessResp{
Token: value.Get("access_token"),
Refresh: value.Get("refresh_token"),
Expires: time.Now().Unix() + expires,
}
return resp, nil
}
// qqOpenID .
func (d *Dao) qqOpenID(c context.Context, token string, business int) (resp *model.QQOpenIDResp, err error) {
var (
res *http.Response
bs []byte
params = url.Values{}
)
params.Set("access_token", token)
params.Set("unionid", "1")
// TODO 如果后续要支持没有unionid权限的appid可以考虑在sns_apps表增加unionid权限标识的字段
//if business == model.BusinessMall {
// params.Set("unionid", "1")
//}
if res, err = d.client.Get(_qqOpenIDUrl + "?" + params.Encode()); err != nil {
log.Error("d.qqOpenID error(%+v) token(%d) business(%d)", err, token, business)
return nil, err
}
defer res.Body.Close()
if bs, err = ioutil.ReadAll(res.Body); err != nil {
log.Error("ioutil.ReadAll() error(%+v) token(%d) business(%d)", err, token, business)
return nil, err
}
respStr := string(bs)
if strings.HasPrefix(respStr, "callback") {
start := strings.Index(respStr, "{")
end := strings.Index(respStr, "}")
respStr = respStr[start : end+1]
}
resp = new(model.QQOpenIDResp)
if err = json.Unmarshal([]byte(respStr), resp); err != nil {
return nil, err
}
if resp.Code == _respCodeSuccess {
return resp, nil
}
log.Error("request qq openid failed with code(%d) desc(%s)", resp.Code, resp.Description)
return nil, ecode.PassportSnsRequestErr
}

View File

@@ -0,0 +1,84 @@
package dao
import (
"context"
"fmt"
"testing"
"go-common/app/service/main/passport-sns/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDao_QQAuthorize(t *testing.T) {
var (
c = context.Background()
AppID = "101135748"
RedirectUrl = "https://passport.bilibili.com/login/snsback?sns=qq"
Display = "mobile"
// AppID : "1108092926",
// RedirectUrl : "https://passport.bilibili.com/web/sns/bind/callback/qq",
)
convey.Convey("QQAuthorize", t, func(ctx convey.C) {
res := d.QQAuthorize(c, AppID, RedirectUrl, Display)
ctx.Convey("Then res should not be nil.", func(ctx convey.C) {
ctx.So(res, convey.ShouldNotBeNil)
})
fmt.Println(res)
})
}
func TestDao_QQOauth2Info(t *testing.T) {
var (
c = context.Background()
code = "C4946CD493AEEDE67C574DFE2C756D09"
redirectUrl = "https://passport.bilibili.com/web/sns/bind/callback"
app = &model.SnsApps{
AppID: "",
AppSecret: "",
Business: model.BusinessMall,
}
)
convey.Convey("QQSnsInfo", t, func(ctx convey.C) {
res, err := d.QQOauth2Info(c, code, redirectUrl, app)
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)
})
fmt.Printf("(%+v) error(%+v)", res, err)
})
}
func TestDao_qqAccessToken(t *testing.T) {
var (
c = context.Background()
code = "CF8CE1408E8E43E4CD2DC778B5993FBB"
appID = ""
appSecret = ""
redirectUrl = "https://passport.bilibili.com/web/sns/bind/callback"
)
convey.Convey("qqAccessToken", t, func(ctx convey.C) {
res, err := d.qqAccessToken(c, code, appID, appSecret, redirectUrl)
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)
})
fmt.Printf("(%+v) error(%+v)", res, err)
})
}
func TestDao_qqOpenID(t *testing.T) {
var (
c = context.Background()
token = ""
business = model.BusinessMall
)
convey.Convey("qqOpenID", t, func(ctx convey.C) {
res, err := d.qqOpenID(c, token, business)
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.ShouldNotBeEmpty)
})
fmt.Printf("(%+v) error(%+v)", res, err)
})
}

View File

@@ -0,0 +1,200 @@
package dao
import (
"context"
"database/sql"
"fmt"
"hash/crc32"
"go-common/app/service/main/passport-sns/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_getSnsAppsSQL = "SELECT appid,appsecret,platform,business FROM sns_apps"
_getSnsUsersSQL = "SELECT mid,unionid,platform,expires FROM sns_user WHERE mid = ?"
_getSnsTokensSQL = "SELECT mid,openid,unionid,platform,token,expires FROM sns_token WHERE mid = ?"
_getSnsUserByMidSQL = "SELECT mid,unionid,platform FROM sns_user WHERE mid = ? and platform = ?"
_getSnsUserByUnionIDSQL = "SELECT mid,unionid,platform FROM sns_user WHERE unionid = ? and platform = ?"
_addSnsUserSQL = "INSERT INTO sns_user (mid,unionid,platform,expires) VALUES(?,?,?,?)"
_addSnsOpenIDSQL = "INSERT IGNORE INTO sns_openid_%02d (openid,unionid,appid,platform) VALUES(?,?,?,?)"
_addSnsTokenSQL = "INSERT INTO sns_token (mid,openid,unionid,platform,token,expires,appid) VALUES(?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE mid=?, openid =?, token =?, expires =?, appid =?"
_updateSnsTokenSQL = "UPDATE sns_token SET token =?, expires =? WHERE mid =? and platform = ?"
_updateSnsUserSQL = "UPDATE sns_user SET expires =? WHERE mid =? and platform =?"
_delSnsUserSQL = "DELETE FROM sns_user WHERE mid = ? and platform = ?"
_delSnsUsersSQL = "DELETE FROM sns_user WHERE mid = ?"
)
// SnsApps get sns apps
func (d *Dao) SnsApps(c context.Context) (res []*model.SnsApps, err error) {
var rows *xsql.Rows
if rows, err = d.db.Query(c, _getSnsAppsSQL); err != nil {
log.Error("SnsApps dao.db.Query error(%+v)", err)
return
}
res = make([]*model.SnsApps, 0)
defer rows.Close()
for rows.Next() {
r := new(model.SnsApps)
if err = rows.Scan(&r.AppID, &r.AppSecret, &r.Platform, &r.Business); err != nil {
log.Error("SnsApps row.Scan() error(%+v)", err)
res = nil
return
}
res = append(res, r)
}
return
}
// SnsUsers get sns users
func (d *Dao) SnsUsers(c context.Context, mid int64) (res []*model.SnsUser, err error) {
var rows *xsql.Rows
if rows, err = d.db.Query(c, _getSnsUsersSQL, mid); err != nil {
log.Error("SnsUsers dao.db.Query error(%+v)", err)
return
}
res = make([]*model.SnsUser, 0)
defer rows.Close()
for rows.Next() {
r := new(model.SnsUser)
if err = rows.Scan(&r.Mid, &r.UnionID, &r.Platform, &r.Expires); err != nil {
log.Error("SnsUsers row.Scan() error(%+v)", err)
res = nil
return
}
res = append(res, r)
}
return
}
// SnsTokens get sns tokens
func (d *Dao) SnsTokens(c context.Context, mid int64) (res []*model.SnsToken, err error) {
var rows *xsql.Rows
if rows, err = d.db.Query(c, _getSnsTokensSQL, mid); err != nil {
log.Error("SnsTokens dao.db.Query error(%+v)", err)
return
}
res = make([]*model.SnsToken, 0)
defer rows.Close()
for rows.Next() {
r := new(model.SnsToken)
if err = rows.Scan(&r.Mid, &r.OpenID, &r.UnionID, &r.Platform, &r.Token, &r.Expires); err != nil {
log.Error("SnsTokens row.Scan() error(%+v)", err)
res = nil
return
}
res = append(res, r)
}
return
}
// SnsUserByMid get sns user by mid and platform
func (d *Dao) SnsUserByMid(c context.Context, mid int64, platform int) (res *model.SnsUser, err error) {
res = new(model.SnsUser)
row := d.db.QueryRow(c, _getSnsUserByMidSQL, mid, platform)
if err = row.Scan(&res.Mid, &res.UnionID, &res.Platform); err != nil {
if err == xsql.ErrNoRows {
err = nil
res = nil
return
}
log.Error("SnsUserByMid mid(%d) platform(%d) row.Scan() error(%+v)", mid, platform, err)
return
}
return
}
// SnsUserByUnionID get sns user by unionID and platform
func (d *Dao) SnsUserByUnionID(c context.Context, unionID string, platform int) (res *model.SnsUser, err error) {
res = new(model.SnsUser)
row := d.db.QueryRow(c, _getSnsUserByUnionIDSQL, unionID, platform)
if err = row.Scan(&res.Mid, &res.UnionID, &res.Platform); err != nil {
if err == xsql.ErrNoRows {
err = nil
res = nil
return
}
log.Error("SnsUserByUnionID unionID(%s) platform(%d) row.Scan() error(%+v)", unionID, platform, err)
return
}
return
}
// TxAddSnsUser add sns user.
func (d *Dao) TxAddSnsUser(tx *xsql.Tx, a *model.SnsUser) (affected int64, err error) {
var res sql.Result
if res, err = tx.Exec(_addSnsUserSQL, a.Mid, a.UnionID, a.Platform, a.Expires); err != nil {
log.Error("TxAddSnsUser(%+v) tx.Exec() error(%+v)", a, err)
return
}
return res.RowsAffected()
}
// TxAddSnsOpenID add sns openid.
func (d *Dao) TxAddSnsOpenID(tx *xsql.Tx, a *model.SnsOpenID) (affected int64, err error) {
var res sql.Result
if res, err = tx.Exec(fmt.Sprintf(_addSnsOpenIDSQL, openIDSuffix(a.OpenID)), a.OpenID, a.UnionID, a.AppID, a.Platform); err != nil {
log.Error("TxAddSnsOpenID(%+v) tx.Exec() error(%+v)", a, err)
return
}
return res.RowsAffected()
}
// TxAddSnsToken add sns token.
func (d *Dao) TxAddSnsToken(tx *xsql.Tx, a *model.SnsToken) (affected int64, err error) {
var res sql.Result
if res, err = tx.Exec(_addSnsTokenSQL, a.Mid, a.OpenID, a.UnionID, a.Platform, a.Token, a.Expires, a.AppID, a.Mid, a.OpenID, a.Token, a.Expires, a.AppID); err != nil {
log.Error("TxAddSnsToken(%+v) tx.Exec() error(%+v)", a, err)
return
}
return res.RowsAffected()
}
// TxUpdateSnsUser update sns user expires.
func (d *Dao) TxUpdateSnsUser(tx *xsql.Tx, a *model.SnsUser) (affected int64, err error) {
var res sql.Result
if res, err = tx.Exec(_updateSnsUserSQL, a.Expires, a.Mid, a.Platform); err != nil {
log.Error("TxUpdateSnsUser(%+v) tx.Exec() error(%+v)", a, err)
return
}
return res.RowsAffected()
}
// TxUpdateSnsToken update sns token.
func (d *Dao) TxUpdateSnsToken(tx *xsql.Tx, a *model.SnsToken) (affected int64, err error) {
var res sql.Result
if res, err = tx.Exec(_updateSnsTokenSQL, a.Token, a.Expires, a.Mid, a.Platform); err != nil {
log.Error("TxUpdateSnsToken(%+v) tx.Exec() error(%+v)", a, err)
return
}
return res.RowsAffected()
}
// DelSnsUser del sns user.
func (d *Dao) DelSnsUser(c context.Context, mid int64, platform int) (affected int64, err error) {
var res sql.Result
if res, err = d.db.Exec(c, _delSnsUserSQL, mid, platform); err != nil {
log.Error("DelSnsUser mid(%d) platform(%d) d.db.Exec() error(%+v)", mid, platform, err)
return
}
return res.RowsAffected()
}
// DelSnsUsers del sns user by mid.
func (d *Dao) DelSnsUsers(c context.Context, mid int64) (affected int64, err error) {
var res sql.Result
if res, err = d.db.Exec(c, _delSnsUsersSQL, mid); err != nil {
log.Error("DelAllSnsUser mid(%d) d.db.Exec() error(%+v)", mid, err)
return
}
return res.RowsAffected()
}
func openIDSuffix(openID string) int {
v := int(crc32.ChecksumIEEE([]byte(openID)))
if v < 0 {
v = -v
}
return v % 100
}

View File

@@ -0,0 +1,255 @@
package dao
import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"reflect"
"testing"
"go-common/app/service/main/passport-sns/model"
xsql "go-common/library/database/sql"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestDao_SnsApps(t *testing.T) {
convey.Convey("SnsApps", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.SnsApps(c)
ctx.Convey("Then err should be nil.res should not nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDao_SnsUsers(t *testing.T) {
convey.Convey("SnsUsers", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.SnsUsers(c, mid)
ctx.Convey("Then err should be nil.res should not nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDao_SnsTokens(t *testing.T) {
convey.Convey("SnsTokens", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.SnsTokens(c, mid)
ctx.Convey("Then err should be nil.res should not nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDao_SnsUserByMid(t *testing.T) {
convey.Convey("SnsUserByMid", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
platform = model.PlatformQQ
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.SnsUserByMid(c, mid, platform)
ctx.Convey("Then err should be nil.res should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDao_SnsUserByUnionID(t *testing.T) {
convey.Convey("SnsUserByUnionID", t, func(ctx convey.C) {
var (
c = context.Background()
unionID = ""
platform = model.PlatformQQ
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.SnsUserByUnionID(c, unionID, platform)
ctx.Convey("Then err should be nil.res should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDao_TxAddSnsUser(t *testing.T) {
convey.Convey("TxAddSnsUser", t, func(ctx convey.C) {
var (
tx, _ = d.BeginTran(context.Background())
a = &model.SnsUser{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
mock := monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Exec", func(_ *xsql.Tx, _ string, _ ...interface{}) (res sql.Result, err error) {
return driver.RowsAffected(1), nil
})
defer mock.Unpatch()
affected, err := d.TxAddSnsUser(tx, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDao_TxAddSnsOpenID(t *testing.T) {
convey.Convey("TxAddSnsOpenID", t, func(ctx convey.C) {
var (
tx, _ = d.BeginTran(context.Background())
a = &model.SnsOpenID{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
mock := monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Exec", func(_ *xsql.Tx, _ string, _ ...interface{}) (res sql.Result, err error) {
return driver.RowsAffected(1), nil
})
defer mock.Unpatch()
affected, err := d.TxAddSnsOpenID(tx, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDao_TxAddSnsToken(t *testing.T) {
convey.Convey("TxAddSnsToken", t, func(ctx convey.C) {
var (
tx, _ = d.BeginTran(context.Background())
a = &model.SnsToken{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
mock := monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Exec", func(_ *xsql.Tx, _ string, _ ...interface{}) (res sql.Result, err error) {
return driver.RowsAffected(1), nil
})
defer mock.Unpatch()
affected, err := d.TxAddSnsToken(tx, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDao_TxUpdateSnsUser(t *testing.T) {
convey.Convey("TxUpdateSnsUser", t, func(ctx convey.C) {
var (
tx, _ = d.BeginTran(context.Background())
a = &model.SnsUser{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
mock := monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Exec", func(_ *xsql.Tx, _ string, _ ...interface{}) (res sql.Result, err error) {
return driver.RowsAffected(1), nil
})
defer mock.Unpatch()
affected, err := d.TxUpdateSnsUser(tx, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDao_TxUpdateSnsToken(t *testing.T) {
convey.Convey("TxUpdateSnsToken", t, func(ctx convey.C) {
var (
tx, _ = d.BeginTran(context.Background())
a = &model.SnsToken{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
mock := monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Exec", func(_ *xsql.Tx, _ string, _ ...interface{}) (res sql.Result, err error) {
return driver.RowsAffected(1), nil
})
defer mock.Unpatch()
affected, err := d.TxUpdateSnsToken(tx, a)
ctx.Convey("Then err should be nil.affected should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affected, convey.ShouldNotBeNil)
})
})
})
}
func TestDao_DelSnsUser(t *testing.T) {
convey.Convey("DelSnsUser", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
platform = model.PlatformQQ
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Exec", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (res sql.Result, err error) {
return driver.RowsAffected(1), nil
})
defer mock.Unpatch()
affected, err := d.DelSnsUser(c, mid, platform)
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 TestDao_DelAllSnsUser(t *testing.T) {
convey.Convey("DelAllSnsUser", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
mock := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Exec", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (res sql.Result, err error) {
return driver.RowsAffected(1), nil
})
defer mock.Unpatch()
affected, err := d.DelSnsUsers(c, mid)
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 TestDao_openIDSuffix(t *testing.T) {
convey.Convey("openIDSuffix", t, func(ctx convey.C) {
res := openIDSuffix("test")
fmt.Println(res)
ctx.Convey("Then res should not be nil.", func(ctx convey.C) {
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,70 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"time"
"go-common/app/service/main/passport-sns/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_weiboAuthorizeUrl = "https://api.weibo.com/oauth2/authorize"
_weiboAccessTokenUrl = "https://api.weibo.com/oauth2/access_token"
)
// WeiboAuthorize .
func (d *Dao) WeiboAuthorize(c context.Context, appID, redirectURL, display string) (url string) {
return fmt.Sprintf(_weiboAuthorizeUrl+"?client_id=%s&redirect_uri=%s&scope=all", appID, redirectURL)
}
// WeiboOauth2Info .
func (d *Dao) WeiboOauth2Info(c context.Context, code, redirectUrl string, app *model.SnsApps) (res *model.Oauth2Info, err error) {
accessResp, err := d.weiboAccessToken(c, code, app.AppID, app.AppSecret, redirectUrl)
if err != nil {
return nil, err
}
res = &model.Oauth2Info{
Token: accessResp.Token,
Refresh: accessResp.Refresh,
Expires: time.Now().Unix() + accessResp.Expires,
OpenID: accessResp.OpenID,
UnionID: accessResp.OpenID,
}
return
}
// weiboAccessToken .
func (d *Dao) weiboAccessToken(c context.Context, code, appID, appSecret, redirectUrl string) (resp *model.WeiboAccessResp, err error) {
var (
res *http.Response
params = url.Values{}
)
params.Set("client_id", appID)
params.Set("client_secret", appSecret)
params.Set("grant_type", "authorization_code")
params.Set("code", code)
params.Set("redirect_uri", redirectUrl)
res, err = d.client.PostForm(_weiboAccessTokenUrl, params)
if err != nil {
log.Error("d.weiboAccessToken error(%+v) code(%s) appID(%s)", err, code, appID)
return nil, err
}
defer res.Body.Close()
dc := json.NewDecoder(res.Body)
resp = new(model.WeiboAccessResp)
if err = dc.Decode(resp); err != nil {
return
}
if resp.Code == _respCodeSuccess {
return resp, nil
}
log.Error("request weibo failed with code(%d) desc(%s)", resp.Code, resp.Description)
return nil, ecode.PassportSnsRequestErr
}

View File

@@ -0,0 +1,68 @@
package dao
import (
"context"
"fmt"
"testing"
"go-common/app/service/main/passport-sns/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDao_WeiboAuthorize(t *testing.T) {
var (
c = context.Background()
AppID = "101135748"
RedirectUrl = "https://passport.bilibili.com/login/snsback?sns=weibo"
Display = "mobile"
// AppID : "1108092926",
// RedirectUrl : "https://passport.bilibili.com/web/sns/bind/callback/weibo",
)
convey.Convey("WeiboAuthorize", t, func(ctx convey.C) {
res := d.WeiboAuthorize(c, AppID, RedirectUrl, Display)
ctx.Convey("Then res should not be nil.", func(ctx convey.C) {
ctx.So(res, convey.ShouldNotBeNil)
})
fmt.Println(res)
})
}
func TestDao_WeiboOauth2Info(t *testing.T) {
var (
c = context.Background()
code = "C4946CD493AEEDE67C574DFE2C756D09"
redirectUrl = "https://passport.bilibili.com/web/sns/bind/callback"
app = &model.SnsApps{
AppID: "",
AppSecret: "",
Business: model.BusinessMall,
}
)
convey.Convey("WeiboOauth2Info", t, func(ctx convey.C) {
res, err := d.WeiboOauth2Info(c, code, redirectUrl, app)
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)
})
fmt.Printf("(%+v) error(%+v)", res, err)
})
}
func TestDao_weiboAccessToken(t *testing.T) {
var (
c = context.Background()
code = "CF8CE1408E8E43E4CD2DC778B5993FBB"
appID = ""
appSecret = ""
redirectUrl = "https://passport.bilibili.com/web/sns/bind/callback"
)
convey.Convey("weiboAccessToken", t, func(ctx convey.C) {
res, err := d.weiboAccessToken(c, code, appID, appSecret, redirectUrl)
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)
})
fmt.Printf("(%+v) error(%+v)", res, err)
})
}

View File

@@ -0,0 +1,60 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"const.go",
"qq.go",
"sns.go",
"weibo.go",
],
embed = [":model_go_proto"],
importpath = "go-common/app/service/main/passport-sns/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/passport-sns/api: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 = ["sns.proto"],
tags = ["automanaged"],
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-sns/model",
proto = ":model_proto",
tags = ["automanaged"],
deps = ["@com_github_gogo_protobuf//gogoproto:go_default_library"],
)

View File

@@ -0,0 +1,25 @@
package model
// platform
const (
PlatformQQ = 1
PlatformWEIBO = 2
PlatformAll = "all"
PlatformQQStr = "qq"
PlatformWEIBOStr = "weibo"
)
// business
const (
BusinessMain = 10
BusinessMall = 20
)
// operate
const (
OperateBind = 1
OperateUnbind = 2
OperateDelete = 3
OperateLogin = 4
)

View File

@@ -0,0 +1,7 @@
#! /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

View File

@@ -0,0 +1,18 @@
package model
// QQAccessResp qq access response
type QQAccessResp struct {
Token string `json:"access_token"`
Refresh string `json:"refresh_token"`
Expires int64 `json:"expires_in"`
Code int `json:"error"`
Description string `json:"error_description"`
}
// QQOpenIDResp qq open id response
type QQOpenIDResp struct {
UnionID string `json:"unionid"`
OpenID string `json:"openid"`
Code int `json:"error"`
Description string `json:"error_description"`
}

View File

@@ -0,0 +1,98 @@
package model
import (
"go-common/app/service/main/passport-sns/api"
)
// SnsApps .
type SnsApps struct {
AppID string
AppSecret string
Platform int
Business int
}
// SnsUser .
type SnsUser struct {
Mid int64 `json:"mid"`
UnionID string `json:"unionid"`
Platform int `json:"platform"`
Expires int64 `json:"expires"`
}
// SnsOpenID .
type SnsOpenID struct {
Mid int64 `json:"mid"`
OpenID string `json:"openid"`
UnionID string `json:"unionid"`
AppID string `json:"appid"`
Platform int `json:"platform"`
}
// SnsToken .
type SnsToken struct {
Mid int64 `json:"mid"`
OpenID string `json:"openid"`
UnionID string `json:"unionid"`
Platform int `json:"platform"`
Token string `json:"token"`
Expires int64 `json:"expires"`
AppID string `json:"appid"`
}
// SnsLog .
type SnsLog struct {
Mid int64 `json:"mid"`
OpenID string `json:"openid"`
UnionID string `json:"unionid"`
AppID string `json:"appid"`
Platform int `json:"platform"`
Operator string `json:"operator"`
Operate int `json:"operate"`
Description string `json:"description"`
}
// CheckBindResp .
type CheckBindResp struct {
Bind bool `json:"bind"`
Mid int64 `json:"mid"`
}
// Oauth2Info oauth2 info
type Oauth2Info struct {
UnionID string `json:"unionid"`
OpenID string `json:"openid"`
Token string `json:"access_token"`
Refresh string `json:"refresh_token"`
Expires int64 `json:"expires"`
}
// ConvertToProto .
func (t *SnsUser) ConvertToProto() *SnsProto {
return &SnsProto{
Mid: t.Mid,
UnionID: t.UnionID,
Platform: int32(t.Platform),
Expires: t.Expires,
}
}
// ConvertToInfo .
func (p *SnsProto) ConvertToInfo() *api.Info {
return &api.Info{
Mid: p.Mid,
Platform: parsePlatformStr(p.Platform),
UnionId: p.UnionID,
Expires: p.Expires,
}
}
func parsePlatformStr(platform int32) string {
switch platform {
case PlatformQQ:
return PlatformQQStr
case PlatformWEIBO:
return PlatformWEIBOStr
}
return ""
}

View File

@@ -0,0 +1,799 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: sns.proto
/*
Package model is a generated protocol buffer package.
It is generated from these files:
sns.proto
It has these top-level messages:
SnsProto
Oauth2Proto
*/
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
type SnsProto struct {
Mid int64 `protobuf:"varint,1,opt,name=Mid,proto3" json:"mid"`
UnionID string `protobuf:"bytes,2,opt,name=UnionID,proto3" json:"unionid"`
Platform int32 `protobuf:"varint,3,opt,name=Platform,proto3" json:"platform"`
Expires int64 `protobuf:"varint,4,opt,name=Expires,proto3" json:"expires"`
}
func (m *SnsProto) Reset() { *m = SnsProto{} }
func (m *SnsProto) String() string { return proto.CompactTextString(m) }
func (*SnsProto) ProtoMessage() {}
func (*SnsProto) Descriptor() ([]byte, []int) { return fileDescriptorSns, []int{0} }
func (m *SnsProto) GetMid() int64 {
if m != nil {
return m.Mid
}
return 0
}
func (m *SnsProto) GetUnionID() string {
if m != nil {
return m.UnionID
}
return ""
}
func (m *SnsProto) GetPlatform() int32 {
if m != nil {
return m.Platform
}
return 0
}
func (m *SnsProto) GetExpires() int64 {
if m != nil {
return m.Expires
}
return 0
}
type Oauth2Proto struct {
Mid int64 `protobuf:"varint,1,opt,name=Mid,proto3" json:"mid"`
UnionID string `protobuf:"bytes,2,opt,name=UnionID,proto3" json:"unionid"`
OpenID string `protobuf:"bytes,3,opt,name=OpenID,proto3" json:"openid"`
Platform int32 `protobuf:"varint,4,opt,name=Platform,proto3" json:"platform"`
AppID string `protobuf:"bytes,5,opt,name=AppID,proto3" json:"appid"`
Token string `protobuf:"bytes,6,opt,name=Token,proto3" json:"token"`
Expires int64 `protobuf:"varint,7,opt,name=Expires,proto3" json:"expires"`
}
func (m *Oauth2Proto) Reset() { *m = Oauth2Proto{} }
func (m *Oauth2Proto) String() string { return proto.CompactTextString(m) }
func (*Oauth2Proto) ProtoMessage() {}
func (*Oauth2Proto) Descriptor() ([]byte, []int) { return fileDescriptorSns, []int{1} }
func (m *Oauth2Proto) GetMid() int64 {
if m != nil {
return m.Mid
}
return 0
}
func (m *Oauth2Proto) GetUnionID() string {
if m != nil {
return m.UnionID
}
return ""
}
func (m *Oauth2Proto) GetOpenID() string {
if m != nil {
return m.OpenID
}
return ""
}
func (m *Oauth2Proto) GetPlatform() int32 {
if m != nil {
return m.Platform
}
return 0
}
func (m *Oauth2Proto) GetAppID() string {
if m != nil {
return m.AppID
}
return ""
}
func (m *Oauth2Proto) GetToken() string {
if m != nil {
return m.Token
}
return ""
}
func (m *Oauth2Proto) GetExpires() int64 {
if m != nil {
return m.Expires
}
return 0
}
func init() {
proto.RegisterType((*SnsProto)(nil), "passport.service.sns.SnsProto")
proto.RegisterType((*Oauth2Proto)(nil), "passport.service.sns.Oauth2Proto")
}
func (m *SnsProto) 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 *SnsProto) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Mid != 0 {
dAtA[i] = 0x8
i++
i = encodeVarintSns(dAtA, i, uint64(m.Mid))
}
if len(m.UnionID) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintSns(dAtA, i, uint64(len(m.UnionID)))
i += copy(dAtA[i:], m.UnionID)
}
if m.Platform != 0 {
dAtA[i] = 0x18
i++
i = encodeVarintSns(dAtA, i, uint64(m.Platform))
}
if m.Expires != 0 {
dAtA[i] = 0x20
i++
i = encodeVarintSns(dAtA, i, uint64(m.Expires))
}
return i, nil
}
func (m *Oauth2Proto) 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 *Oauth2Proto) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Mid != 0 {
dAtA[i] = 0x8
i++
i = encodeVarintSns(dAtA, i, uint64(m.Mid))
}
if len(m.UnionID) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintSns(dAtA, i, uint64(len(m.UnionID)))
i += copy(dAtA[i:], m.UnionID)
}
if len(m.OpenID) > 0 {
dAtA[i] = 0x1a
i++
i = encodeVarintSns(dAtA, i, uint64(len(m.OpenID)))
i += copy(dAtA[i:], m.OpenID)
}
if m.Platform != 0 {
dAtA[i] = 0x20
i++
i = encodeVarintSns(dAtA, i, uint64(m.Platform))
}
if len(m.AppID) > 0 {
dAtA[i] = 0x2a
i++
i = encodeVarintSns(dAtA, i, uint64(len(m.AppID)))
i += copy(dAtA[i:], m.AppID)
}
if len(m.Token) > 0 {
dAtA[i] = 0x32
i++
i = encodeVarintSns(dAtA, i, uint64(len(m.Token)))
i += copy(dAtA[i:], m.Token)
}
if m.Expires != 0 {
dAtA[i] = 0x38
i++
i = encodeVarintSns(dAtA, i, uint64(m.Expires))
}
return i, nil
}
func encodeVarintSns(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 *SnsProto) Size() (n int) {
var l int
_ = l
if m.Mid != 0 {
n += 1 + sovSns(uint64(m.Mid))
}
l = len(m.UnionID)
if l > 0 {
n += 1 + l + sovSns(uint64(l))
}
if m.Platform != 0 {
n += 1 + sovSns(uint64(m.Platform))
}
if m.Expires != 0 {
n += 1 + sovSns(uint64(m.Expires))
}
return n
}
func (m *Oauth2Proto) Size() (n int) {
var l int
_ = l
if m.Mid != 0 {
n += 1 + sovSns(uint64(m.Mid))
}
l = len(m.UnionID)
if l > 0 {
n += 1 + l + sovSns(uint64(l))
}
l = len(m.OpenID)
if l > 0 {
n += 1 + l + sovSns(uint64(l))
}
if m.Platform != 0 {
n += 1 + sovSns(uint64(m.Platform))
}
l = len(m.AppID)
if l > 0 {
n += 1 + l + sovSns(uint64(l))
}
l = len(m.Token)
if l > 0 {
n += 1 + l + sovSns(uint64(l))
}
if m.Expires != 0 {
n += 1 + sovSns(uint64(m.Expires))
}
return n
}
func sovSns(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozSns(x uint64) (n int) {
return sovSns(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *SnsProto) 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 ErrIntOverflowSns
}
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: SnsProto: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: SnsProto: 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 ErrIntOverflowSns
}
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 UnionID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSns
}
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 ErrInvalidLengthSns
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.UnionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Platform", wireType)
}
m.Platform = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Platform |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
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 ErrIntOverflowSns
}
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 := skipSns(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthSns
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Oauth2Proto) 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 ErrIntOverflowSns
}
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: Oauth2Proto: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Oauth2Proto: 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 ErrIntOverflowSns
}
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 UnionID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSns
}
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 ErrInvalidLengthSns
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.UnionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field OpenID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSns
}
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 ErrInvalidLengthSns
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.OpenID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Platform", wireType)
}
m.Platform = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Platform |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AppID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSns
}
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 ErrInvalidLengthSns
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AppID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Token", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSns
}
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 ErrInvalidLengthSns
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Token = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
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 ErrIntOverflowSns
}
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 := skipSns(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthSns
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipSns(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, ErrIntOverflowSns
}
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, ErrIntOverflowSns
}
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, ErrIntOverflowSns
}
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, ErrInvalidLengthSns
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSns
}
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 := skipSns(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 (
ErrInvalidLengthSns = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowSns = fmt.Errorf("proto: integer overflow")
)
func init() { proto.RegisterFile("sns.proto", fileDescriptorSns) }
var fileDescriptorSns = []byte{
// 326 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x91, 0x3f, 0x4e, 0xf3, 0x30,
0x18, 0xc6, 0x3f, 0x37, 0x4d, 0xd2, 0xba, 0xdf, 0x54, 0x21, 0x61, 0x18, 0xe2, 0xaa, 0x12, 0x52,
0x16, 0x52, 0x09, 0x4e, 0x40, 0x54, 0x86, 0x0e, 0xa8, 0x95, 0x81, 0x85, 0x2d, 0x6d, 0xdc, 0xd6,
0xa2, 0xb1, 0xad, 0xd8, 0x41, 0x9c, 0x80, 0x33, 0xb0, 0x70, 0x1f, 0x46, 0x4e, 0x10, 0xa1, 0xb0,
0xe5, 0x14, 0xc8, 0x4e, 0xcb, 0x9f, 0x01, 0x26, 0xb6, 0xbc, 0xbf, 0xe7, 0xa7, 0x27, 0x79, 0xdf,
0xc0, 0xae, 0xe2, 0x2a, 0x92, 0xb9, 0xd0, 0xa2, 0xbf, 0x27, 0x13, 0xa5, 0xa4, 0xc8, 0x75, 0xa4,
0x68, 0x7e, 0xc7, 0x16, 0x34, 0x52, 0x5c, 0x1d, 0x1e, 0xaf, 0x98, 0x5e, 0x17, 0xf3, 0x68, 0x21,
0xb2, 0xd1, 0x4a, 0xac, 0xc4, 0xc8, 0xca, 0xf3, 0x62, 0x69, 0x27, 0x3b, 0xd8, 0xa7, 0xa6, 0x64,
0xf8, 0x04, 0x60, 0xe7, 0x92, 0xab, 0x99, 0x6d, 0x3c, 0x80, 0xce, 0x05, 0x4b, 0x11, 0x18, 0x80,
0xd0, 0x89, 0xfd, 0xba, 0xc4, 0x4e, 0xc6, 0x52, 0x62, 0x58, 0xff, 0x08, 0xfa, 0xd7, 0x9c, 0x09,
0x3e, 0x19, 0xa3, 0xd6, 0x00, 0x84, 0xdd, 0xb8, 0x57, 0x97, 0xd8, 0x2f, 0x0c, 0x62, 0x29, 0xd9,
0x65, 0xfd, 0x10, 0x76, 0x66, 0x9b, 0x44, 0x2f, 0x45, 0x9e, 0x21, 0x67, 0x00, 0x42, 0x37, 0xfe,
0x5f, 0x97, 0xb8, 0x23, 0xb7, 0x8c, 0x7c, 0xa4, 0xa6, 0xf0, 0xfc, 0x5e, 0xb2, 0x9c, 0x2a, 0xd4,
0xb6, 0xef, 0xb3, 0x85, 0xb4, 0x41, 0x64, 0x97, 0x0d, 0x1f, 0x5a, 0xb0, 0x37, 0x4d, 0x0a, 0xbd,
0x3e, 0xf9, 0xab, 0x4f, 0x1c, 0x42, 0x6f, 0x2a, 0xa9, 0xb1, 0x1c, 0x6b, 0xc1, 0xba, 0xc4, 0x9e,
0x90, 0xd4, 0x48, 0xdb, 0xe4, 0xdb, 0x1a, 0xed, 0x5f, 0xd7, 0xc0, 0xd0, 0x3d, 0x93, 0x72, 0x32,
0x46, 0xae, 0x2d, 0xeb, 0xd6, 0x25, 0x76, 0x13, 0x29, 0x59, 0x4a, 0x1a, 0x6e, 0x84, 0x2b, 0x71,
0x4b, 0x39, 0xf2, 0x3e, 0x05, 0x6d, 0x00, 0x69, 0xf8, 0xd7, 0x43, 0xf8, 0x3f, 0x1f, 0x22, 0xde,
0x7f, 0xae, 0x02, 0xf0, 0x52, 0x05, 0xe0, 0xb5, 0x0a, 0xc0, 0xe3, 0x5b, 0xf0, 0xef, 0xc6, 0xcd,
0x44, 0x4a, 0x37, 0x73, 0xcf, 0xfe, 0xc8, 0xd3, 0xf7, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6e, 0x2d,
0x91, 0x85, 0x1a, 0x02, 0x00, 0x00,
}

View File

@@ -0,0 +1,22 @@
syntax = "proto3";
package passport.service.sns;
option go_package = "model";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
message SnsProto {
int64 Mid = 1 [(gogoproto.jsontag) = "mid"];
string UnionID = 2 [(gogoproto.jsontag) = "unionid"];
int32 Platform = 3 [(gogoproto.jsontag) = "platform"];
int64 Expires = 4 [(gogoproto.jsontag) = "expires"];
}
message Oauth2Proto {
int64 Mid = 1 [(gogoproto.jsontag) = "mid"];
string UnionID = 2 [(gogoproto.jsontag) = "unionid"];
string OpenID = 3 [(gogoproto.jsontag) = "openid"];
int32 Platform = 4 [(gogoproto.jsontag) = "platform"];
string AppID = 5 [(gogoproto.jsontag) = "appid"];
string Token = 6 [(gogoproto.jsontag) = "token"];
int64 Expires = 7 [(gogoproto.jsontag) = "expires"];
}

View File

@@ -0,0 +1,12 @@
package model
// WeiboAccessResp weibo access response
type WeiboAccessResp struct {
Token string `json:"access_token"`
Refresh string `json:"refresh_token"`
Expires int64 `json:"expires_in"` // access_token的生命周期单位是秒数
OpenID string `json:"uid"`
Code int `json:"error_code"`
Error string `json:"error"`
Description string `json:"error_description"`
}

View File

@@ -0,0 +1,36 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["server.go"],
importpath = "go-common/app/service/main/passport-sns/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/passport-sns/api:go_default_library",
"//app/service/main/passport-sns/conf:go_default_library",
"//app/service/main/passport-sns/service:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,29 @@
package http
import (
"go-common/app/service/main/passport-sns/api"
"go-common/app/service/main/passport-sns/conf"
"go-common/app/service/main/passport-sns/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
svr *service.Service
vfy *verify.Verify
)
// Init init config
func Init(c *conf.Config) {
svr = service.New(c)
vfy = verify.New(c.Verify)
e := bm.DefaultServer(c.BM)
e.Inject("/x/internal/passport-sns/", vfy.Verify)
// 生成工具还不支持,需要后续优化
e.Ping(func(c *bm.Context) {})
api.RegisterPassportSNSBMServer(e, svr)
if err := e.Start(); err != nil {
log.Error("bm.DefaultServer error(%v)", err)
}
}

View File

@@ -0,0 +1,41 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"service.go",
"sns.go",
],
importpath = "go-common/app/service/main/passport-sns/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/passport-sns/api:go_default_library",
"//app/service/main/passport-sns/conf:go_default_library",
"//app/service/main/passport-sns/dao:go_default_library",
"//app/service/main/passport-sns/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/queue/databus:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,120 @@
package service
import (
"context"
"go-common/app/service/main/passport-sns/conf"
"go-common/app/service/main/passport-sns/dao"
"go-common/app/service/main/passport-sns/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/queue/databus"
"go-common/library/sync/pipeline/fanout"
)
// Service struct of service
type Service struct {
c *conf.Config
d *dao.Dao
snsLogPub *databus.Databus
job *fanout.Fanout
cache *fanout.Fanout
AppMap map[int]map[string]*model.SnsApps
PlatformList []int
PlatformStrList []string
}
// New create new service
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
d: dao.New(c),
snsLogPub: databus.New(c.DataBus.SnsLogPub),
job: fanout.New("job", fanout.Worker(10), fanout.Buffer(10240)),
cache: fanout.New("cache", fanout.Worker(10), fanout.Buffer(10240)),
PlatformList: []int{model.PlatformQQ, model.PlatformWEIBO},
PlatformStrList: []string{model.PlatformQQStr, model.PlatformWEIBOStr},
}
var err error
s.AppMap, err = s.initAppMap()
if err != nil || s.AppMap == nil {
log.Error("fail to get appMap")
panic(err)
}
return
}
// Ping check server ok.
func (s *Service) Ping(c context.Context) (err error) {
return
}
// Close dao.
func (s *Service) Close() {
s.d.Close()
}
func (s *Service) initAppMap() (res map[int]map[string]*model.SnsApps, err error) {
snsApps, err := s.d.SnsApps(context.Background())
if err != nil {
return
}
res = make(map[int]map[string]*model.SnsApps)
platformMap := make(map[int][]*model.SnsApps)
for _, app := range snsApps {
platformMap[app.Platform] = append(platformMap[app.Platform], app)
}
for k, v := range platformMap {
kMap := make(map[string]*model.SnsApps)
for _, app := range v {
kMap[app.AppID] = app
}
res[k] = kMap
}
return
}
func parsePlatform(platform string) int {
switch platform {
case model.PlatformQQStr:
return model.PlatformQQ
case model.PlatformWEIBOStr:
return model.PlatformWEIBO
}
return 0
}
func parsePlatformStr(platform int) string {
switch platform {
case model.PlatformQQ:
return model.PlatformQQStr
case model.PlatformWEIBO:
return model.PlatformWEIBOStr
}
return ""
}
func (s *Service) isAppID(platform int, appID string) bool {
return s.AppMap[platform][appID] != nil
}
func platformToMidBindErr(platform int) error {
switch platform {
case model.PlatformQQ:
return ecode.PassportSnsMidAlreadyBindQQ
case model.PlatformWEIBO:
return ecode.PassportSnsMidAlreadyBindWEIBO
}
return ecode.ServerErr
}
func platformToSnsBindErr(platform int) error {
switch platform {
case model.PlatformQQ:
return ecode.PassportSnsQQAlreadyBind
case model.PlatformWEIBO:
return ecode.PassportSnsWEIBOAlreadyBind
}
return ecode.ServerErr
}

View File

@@ -0,0 +1,419 @@
package service
import (
"context"
"strconv"
"go-common/app/service/main/passport-sns/api"
"go-common/app/service/main/passport-sns/model"
"go-common/library/ecode"
"go-common/library/log"
)
var emptyCache = &model.SnsProto{}
// GetAuthorizeURL get sns authorize url
func (s *Service) GetAuthorizeURL(c context.Context, req *api.GetAuthorizeURLReq) (resp *api.GetAuthorizeURLReply, err error) {
platform := parsePlatform(req.Platform)
if platform == 0 || !s.isAppID(platform, req.AppId) {
return nil, ecode.RequestErr
}
switch platform {
case model.PlatformQQ:
return &api.GetAuthorizeURLReply{Url: s.d.QQAuthorize(c, req.AppId, req.RedirectUrl, req.Display)}, nil
case model.PlatformWEIBO:
return &api.GetAuthorizeURLReply{Url: s.d.WeiboAuthorize(c, req.AppId, req.RedirectUrl, req.Display)}, nil
}
return
}
// Bind bind sns user
func (s *Service) Bind(c context.Context, req *api.BindReq) (resp *api.EmptyReply, err error) {
platform := parsePlatform(req.Platform)
if platform == 0 || !s.isAppID(platform, req.AppId) {
return nil, ecode.RequestErr
}
var u *model.SnsUser
u, err = s.d.SnsUserByMid(c, req.Mid, platform)
if err != nil {
return nil, err
}
if u != nil {
return nil, platformToMidBindErr(platform)
}
var info *model.Oauth2Info
switch platform {
case model.PlatformQQ:
if info, err = s.d.QQOauth2Info(c, req.Code, req.RedirectUrl, s.AppMap[platform][req.AppId]); err != nil {
return nil, err
}
case model.PlatformWEIBO:
if info, err = s.d.WeiboOauth2Info(c, req.Code, req.RedirectUrl, s.AppMap[platform][req.AppId]); err != nil {
return nil, err
}
}
return &api.EmptyReply{}, s.bindSns(c, req.Mid, req.AppId, platform, info)
}
// Unbind unbind sns user
func (s *Service) Unbind(c context.Context, req *api.UnbindReq) (resp *api.EmptyReply, err error) {
if req.Platform == model.PlatformAll {
err = s.unbindAll(c, req.Mid)
return &api.EmptyReply{}, err
}
platform := parsePlatform(req.Platform)
if platform == 0 || !s.isAppID(platform, req.AppId) {
return nil, ecode.RequestErr
}
return &api.EmptyReply{}, s.unbindSns(c, req.Mid, req.AppId, platform)
}
// GetInfo get info by mid
func (s *Service) GetInfo(c context.Context, req *api.GetInfoReq) (resp *api.GetInfoReply, err error) {
addCache := true
snsMap := make(map[string]*model.SnsProto)
for _, platformStr := range s.PlatformStrList {
var sns *model.SnsProto
sns, err = s.d.SnsCache(c, req.Mid, platformStr)
if err != nil {
addCache = false
err = nil
}
snsMap[platformStr] = sns
}
infos := make([]*api.Info, 0)
hitAll := true
for _, platformStr := range s.PlatformStrList {
if snsMap[platformStr] == nil {
hitAll = false
break
}
if snsMap[platformStr].Mid != 0 {
infos = append(infos, snsMap[platformStr].ConvertToInfo())
}
}
if hitAll {
return &api.GetInfoReply{Infos: infos}, nil
}
users, err := s.d.SnsUsers(c, req.Mid)
if err != nil {
return
}
for _, u := range users {
snsMap[parsePlatformStr(u.Platform)] = u.ConvertToProto()
}
infos = make([]*api.Info, 0)
for _, platformStr := range s.PlatformStrList {
if snsMap[platformStr] != nil && snsMap[platformStr].Mid != 0 {
infos = append(infos, snsMap[platformStr].ConvertToInfo())
} else {
snsMap[platformStr] = emptyCache
}
}
if addCache {
s.cache.Do(c, func(c context.Context) {
for _, platformStr := range s.PlatformStrList {
s.d.SetSnsCache(context.Background(), req.Mid, platformStr, snsMap[platformStr])
}
})
}
return &api.GetInfoReply{Infos: infos}, nil
}
// GetInfoByCode get info by code
func (s *Service) GetInfoByCode(c context.Context, req *api.GetInfoByCodeReq) (resp *api.GetInfoByCodeReply, err error) {
platform := parsePlatform(req.Platform)
if platform == 0 || !s.isAppID(platform, req.AppId) {
return nil, ecode.RequestErr
}
var (
info *model.Oauth2Info
mid int64
)
switch platform {
case model.PlatformQQ:
if info, err = s.d.QQOauth2Info(c, req.Code, req.RedirectUrl, s.AppMap[platform][req.AppId]); err != nil {
return nil, err
}
case model.PlatformWEIBO:
if info, err = s.d.WeiboOauth2Info(c, req.Code, req.RedirectUrl, s.AppMap[platform][req.AppId]); err != nil {
return nil, err
}
}
snsUser, err := s.d.SnsUserByUnionID(c, info.UnionID, platform)
if err != nil {
return nil, err
}
if snsUser != nil {
mid = snsUser.Mid
}
proto := &model.Oauth2Proto{
Mid: mid,
Platform: int32(platform),
UnionID: info.UnionID,
OpenID: info.OpenID,
Token: info.Token,
Expires: info.Expires,
AppID: req.AppId,
}
if err = s.d.SetOauth2Cache(c, info.OpenID, req.Platform, proto); err != nil {
return nil, err
}
log.Info("GetInfoByCode request(%+v) response (%+v)", req, &api.GetInfoByCodeReply{
Mid: mid,
UnionId: info.UnionID,
OpenId: info.OpenID,
Expires: info.Expires,
Token: info.Token,
})
return &api.GetInfoByCodeReply{
Mid: mid,
UnionId: info.UnionID,
OpenId: info.OpenID,
Expires: info.Expires,
Token: info.Token,
}, nil
}
// UpdateInfo update info
func (s *Service) UpdateInfo(c context.Context, req *api.UpdateInfoReq) (resp *api.EmptyReply, err error) {
platform := parsePlatform(req.Platform)
if platform == 0 || !s.isAppID(platform, req.AppId) {
return nil, ecode.RequestErr
}
info, err := s.d.Oauth2Cache(c, req.OpenId, req.Platform)
if err != nil {
return nil, err
}
if info == nil {
return nil, ecode.RequestErr
}
s.cache.Do(c, func(c context.Context) {
s.d.DelOauth2Cache(context.Background(), req.OpenId, req.Platform)
})
if info.Mid == 0 {
var u *model.SnsUser
u, err = s.d.SnsUserByMid(c, req.Mid, platform)
if err != nil {
return nil, err
}
if u != nil {
return nil, platformToMidBindErr(platform)
}
oauth2Info := &model.Oauth2Info{
UnionID: info.UnionID,
OpenID: info.OpenID,
Token: info.Token,
Expires: info.Expires,
}
return nil, s.bindSns(c, req.Mid, info.AppID, platform, oauth2Info)
}
tx, err := s.d.BeginTran(context.Background())
if err != nil {
log.Error("s.d.BeginTran error(%+v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("tx.Rollback() error(%v)", err1)
}
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
return
}
snsLog := &model.SnsLog{
Mid: info.Mid,
OpenID: info.OpenID,
UnionID: info.UnionID,
AppID: info.AppID,
Platform: platform,
Operator: "",
Operate: model.OperateLogin,
}
s.job.Do(c, func(c context.Context) {
s.sendSnsLog(context.Background(), snsLog)
})
s.cache.Do(c, func(c context.Context) {
s.d.DelSnsCache(context.Background(), info.Mid, parsePlatformStr(platform))
})
}()
snsUser := &model.SnsUser{
Mid: info.Mid,
Platform: platform,
Expires: info.Expires,
}
if _, err = s.d.TxUpdateSnsUser(tx, snsUser); err != nil {
return
}
snsToken := &model.SnsToken{
Mid: info.Mid,
Platform: platform,
Token: info.Token,
Expires: info.Expires,
}
if _, err = s.d.TxUpdateSnsToken(tx, snsToken); err != nil {
return
}
return
}
func (s *Service) bindSns(c context.Context, mid int64, appID string, platform int, info *model.Oauth2Info) (err error) {
snsUser, err := s.d.SnsUserByUnionID(c, info.UnionID, platform)
if err != nil {
return err
}
if snsUser != nil {
return platformToSnsBindErr(platform)
}
tx, err := s.d.BeginTran(c)
if err != nil {
log.Error("s.d.BeginTran error(%+v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("tx.Rollback() error(%v)", err1)
}
return
}
}()
snsUser = &model.SnsUser{
Mid: mid,
UnionID: info.UnionID,
Platform: platform,
Expires: info.Expires,
}
affected, err := s.d.TxAddSnsUser(tx, snsUser)
if err != nil {
return
}
if affected > 0 {
snsOpenID := &model.SnsOpenID{
Mid: mid,
OpenID: info.OpenID,
UnionID: info.UnionID,
AppID: appID,
Platform: platform,
}
if _, err = s.d.TxAddSnsOpenID(tx, snsOpenID); err != nil {
return
}
snsToken := &model.SnsToken{
Mid: mid,
OpenID: info.OpenID,
UnionID: info.UnionID,
Platform: platform,
Token: info.Token,
Expires: info.Expires,
AppID: appID,
}
if _, err = s.d.TxAddSnsToken(tx, snsToken); err != nil {
return
}
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
return
}
s.cache.Do(c, func(ctx context.Context) {
s.d.DelSnsCache(context.Background(), mid, parsePlatformStr(platform))
})
if affected > 0 {
s.job.Do(c, func(c context.Context) {
snsLog := &model.SnsLog{
Mid: mid,
OpenID: info.OpenID,
UnionID: info.UnionID,
AppID: appID,
Platform: platform,
Operator: "",
Operate: model.OperateBind,
}
s.sendSnsLog(context.Background(), snsLog)
})
}
return
}
func (s *Service) unbindSns(c context.Context, mid int64, appID string, platform int) (err error) {
u, err := s.d.SnsUserByMid(c, mid, platform)
if err != nil {
return
}
affected, err := s.d.DelSnsUser(c, mid, platform)
if err != nil {
return
}
s.cache.Do(c, func(ctx context.Context) {
s.d.DelSnsCache(context.Background(), mid, parsePlatformStr(platform))
})
if affected > 0 {
snsLog := &model.SnsLog{
Mid: mid,
//OpenID: qq.OpenID,
UnionID: u.UnionID,
AppID: appID,
Platform: platform,
Operator: "",
Operate: model.OperateUnbind,
}
s.job.Do(c, func(c context.Context) {
s.sendSnsLog(context.Background(), snsLog)
})
}
return
}
func (s *Service) unbindAll(c context.Context, mid int64) (err error) {
affected, err := s.d.DelSnsUsers(c, mid)
if err != nil {
return
}
s.cache.Do(c, func(ctx context.Context) {
for _, platformStr := range s.PlatformStrList {
s.d.DelSnsCache(context.Background(), mid, platformStr)
}
})
if affected > 0 {
snsLog := &model.SnsLog{
Mid: mid,
Operator: "admin",
Operate: model.OperateDelete,
Description: "删除用户",
}
s.job.Do(c, func(c context.Context) {
s.sendSnsLog(context.Background(), snsLog)
})
}
return
}
func (s *Service) sendSnsLog(c context.Context, snsLog *model.SnsLog) {
for i := 0; i < 3; i++ {
if err := s.snsLogPub.Send(c, strconv.FormatInt(snsLog.Mid, 10), snsLog); err != nil {
log.Error("fail to send snsLog(%+v) error(%+v)", snsLog, err)
continue
}
break
}
}