Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/auth #1

Merged
merged 26 commits into from
Jun 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
.DS_Store

environment.yml
environment.yaml
environment.yaml

temp.go
14 changes: 12 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@ module github.com/ArtisanCloud/go-wechat

go 1.16

//replace github.com/ArtisanCloud/go-libs => ../go-libs
//
//replace github.com/ArtisanCloud/go-socialite => ../go-socialite

require (
github.com/ArtisanCloud/go-libs v1.0.9 // indirect
github.com/ArtisanCloud/ubt-go v1.0.4 // indirect
github.com/ArtisanCloud/go-libs v1.0.11
github.com/ArtisanCloud/go-socialite v1.0.0
github.com/gin-gonic/gin v1.7.1 // indirect
github.com/go-redis/redis/v8 v8.10.0 // indirect
github.com/mattn/go-isatty v0.0.13 // indirect
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
65 changes: 49 additions & 16 deletions go.sum

Large diffs are not rendered by default.

30 changes: 27 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,33 @@
package main

import "fmt"
import (
"fmt"
fmt2 "github.com/ArtisanCloud/go-libs/fmt"
"github.com/ArtisanCloud/go-wechat/src/work"
)

func main() {

fmt.Printf("hello Wechat!")
fmt.Printf("hello Wechat! \n")

}
config := GetConfig()

app := work.NewWork(config)
//fmt2.Dump(app)
fmt2.Dump(app.GetConfig())

//token := app.AccessToken.GetToken()
//fmt2.Dump(token)

//cType := reflect.TypeOf((*app.Components)["base"].(*base.Client))
//fmt.Printf("kind %s \n", cType.Kind())
//fmt.Printf("type %v \n", cType)

//ips := app.Base.GetCallbackIp()
//fmt2.Dump(ips)
//domainIps := app.Base.GetAPIDomainIP()
//fmt2.Dump(domainIps)



}
212 changes: 212 additions & 0 deletions src/kernel/accessToken.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
package kernel

import (
"crypto/md5"
"encoding/json"
"fmt"
"github.com/ArtisanCloud/go-libs/exception"
http2 "github.com/ArtisanCloud/go-libs/http"
httpContract "github.com/ArtisanCloud/go-libs/http/contract"
"github.com/ArtisanCloud/go-libs/object"
"github.com/ArtisanCloud/go-wechat/src/kernel/contract"
response2 "github.com/ArtisanCloud/go-wechat/src/kernel/response"
"net/http"
"time"
)

type AccessToken struct {
App *ApplicationInterface

*http2.HttpRequest
*http2.HttpResponse

RequestMethod string
EndpointToGetToken string
QueryName string
Token object.HashMap
TokenKey string
CachePrefix string

*CacheToken

GetCredentials func() *object.StringMap
}

func NewAccessToken(app *ApplicationInterface) *AccessToken {
config := (*app).GetContainer().GetConfig()

token := &AccessToken{
App: app,
HttpRequest: http2.NewHttpRequest(config),

RequestMethod: "GET",
EndpointToGetToken: "",
QueryName: "",
Token: nil,
TokenKey: "access_token",
CachePrefix: "ac.go.wechat.kernel.access_token.",

CacheToken: &CacheToken{},
}

return token
}

func (accessToken *AccessToken) GetRefreshedToken() *response2.ResponseGetToken {
return accessToken.GetToken(true)
}

func (accessToken *AccessToken) GetToken(refresh bool) (resToken *response2.ResponseGetToken) {
cacheKey := accessToken.getCacheKey()
cache := accessToken.getCache()

// get token from cache
if !refresh && cache.Has(cacheKey) {
value, err := cache.Get(cacheKey, nil)
if err == nil {
token := value.(*object.HashMap)
return &response2.ResponseGetToken{
AccessToken: (*token)[accessToken.TokenKey].(string),
ExpiresIn: (*token)["expires_in"].(int),
}
}
}

// request token from wx
response := accessToken.requestToken(accessToken.GetCredentials())

//// save token into cache
resToken = response.(*response2.ResponseGetToken)
var expireIn int = 7200
if resToken.ExpiresIn > 0 {
expireIn = resToken.ExpiresIn
}
accessToken.SetToken(resToken.AccessToken, expireIn)

// tbd dispatch a event for AccessTokenRefresh

return resToken
}

func (accessToken *AccessToken) SetToken(token string, lifeTime int) (tokenInterface contract.AccessTokenInterface, err error) {
if lifeTime <= 0 {
lifeTime = 7200
}

// set token into cache
cache := accessToken.getCache()
err = cache.Set(accessToken.getCacheKey(), &object.HashMap{
accessToken.TokenKey: token,
"expires_in": lifeTime,
}, time.Duration(lifeTime)*time.Second)

defer (&exception.Exception{}).HandleException(nil, "accessToken.set.token", nil)
if !cache.Has(accessToken.getCacheKey()) {
panic("Failed to cache access token.")
return nil, err
}
return accessToken, err

}

func (accessToken *AccessToken) Refresh() contract.AccessTokenInterface {

return nil
}

func (accessToken *AccessToken) requestToken(credentials *object.StringMap) httpContract.ResponseContract {

// tbf
return &response2.ResponseGetToken{
AccessToken: "FwhFYGuWs47wxxUQHf5gbOIwMBe8ohu3EUnhF-x6uw4VX55-m46bnQUHLJ1nM5R0WAVfrLHvdn6XJtkMkzRkN_E75edrNzWK6IZxx3RwUJNowZEg3dcU3NEygFGfzUEGLS5fiB4GtNPOi-HKUhQumAMcP0lncEij2Hjg95FTqS4YBRNVG4OL92h8RAiP-yllfDvt2URk6tntGe4HaxAGdA",
ExpiresIn: 7200,
ResponseWX: &response2.ResponseWX{
ErrCode: 0,
ErrMSG: "ok",
},
}

res := accessToken.sendRequest(credentials)
token := res.(*response2.ResponseGetToken)
defer (&exception.Exception{}).HandleException(nil, "accessToken.request.token", nil)
if token == nil || token.AccessToken == "" {
panic(fmt.Sprintf("Request access_token fail: %v", res))
return nil
}

return token
}

func (accessToken *AccessToken) ApplyToRequest(request *http.Request, requestOptions *object.HashMap) *http.Request {

// query Access Token map
mapToken := accessToken.getQuery()
q := request.URL.Query()
for key, value := range *mapToken {
q.Set(key, value)
}
request.URL.RawQuery = q.Encode()

return request
}

func (accessToken *AccessToken) sendRequest(credential *object.StringMap) httpContract.ResponseContract {

key := "json"
if accessToken.RequestMethod == "GET" {
key = "query"
}
options := &object.HashMap{
key: credential,
}

res := &response2.ResponseGetToken{}

accessToken.SetHttpClient(accessToken.GetHttpClient()).PerformRequest(
accessToken.getEndpoint(),
accessToken.RequestMethod,
options,
res,
)
return res
}

func (accessToken *AccessToken) getCacheKey() string {
data, _ := json.Marshal(accessToken.GetCredentials())
buffer := md5.Sum(data)

return accessToken.CachePrefix + string(buffer[:])
}

func (accessToken *AccessToken) getQuery() *object.StringMap {
// set the current token key
var key string
if accessToken.QueryName != "" {
key = accessToken.QueryName
} else {
key = accessToken.TokenKey
}

// get token string map
resToken := accessToken.GetToken(false)
arrayReturn := &object.StringMap{
key: resToken.AccessToken,
}

return arrayReturn

}

func (accessToken *AccessToken) getEndpoint() string {
defer (&exception.Exception{}).HandleException(nil, "accessToken.get.endpoint", accessToken)
if accessToken.EndpointToGetToken == "" {
panic("No endpoint for access token request.")
return ""
}

return accessToken.EndpointToGetToken
}

func (accessToken *AccessToken) getTokenKey() string {
return accessToken.TokenKey
}
Loading