mirror of
https://github.com/fumiama/tienyik.git
synced 2026-06-04 23:10:26 +08:00
feat: add more apis
This commit is contained in:
@@ -2,8 +2,14 @@ package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/fumiama/tienyik/internal/hcli"
|
||||
"github.com/fumiama/tienyik"
|
||||
"github.com/fumiama/tienyik/hcli"
|
||||
"github.com/fumiama/tienyik/internal/horm"
|
||||
"github.com/fumiama/tienyik/internal/hson"
|
||||
"github.com/fumiama/tienyik/internal/textio"
|
||||
)
|
||||
@@ -19,11 +25,126 @@ type ResponseNegotiationEncKey struct {
|
||||
EncKey string `json:"encKey"`
|
||||
}
|
||||
|
||||
type ResponseNegotiationEncKeyData struct {
|
||||
EValue string `json:"evalue"`
|
||||
EID string `json:"eid"`
|
||||
}
|
||||
|
||||
func (r *ResponseNegotiationEncKey) Unwrap(tyr *tienyik.RSA) (*ResponseNegotiationEncKeyData, error) {
|
||||
v, err := base64.StdEncoding.DecodeString(r.EncKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aesk, err := tyr.Decrypt(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v, err = base64.StdEncoding.DecodeString(r.EncData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v, err = tienyik.NewAES(aesk).Decrypt(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var rsp ResponseNegotiationEncKeyData
|
||||
err = json.Unmarshal(v, &rsp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rsp, nil
|
||||
}
|
||||
|
||||
func NegotiationEncKey(r *RequestNegotiationEncKey) (*ResponseNegotiationEncKey, error) {
|
||||
resp, err := hcli.Post(textio.API(), bytes.NewReader(hson.Marshal(nil, r)))
|
||||
resp, err := hcli.NoClient.Post(
|
||||
textio.API(), textio.ContenTypeJSON,
|
||||
bytes.NewReader(hson.Marshal(nil, r)),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return hson.Unmarshal[*ResponseNegotiationEncKey](nil, resp.Body)
|
||||
}
|
||||
|
||||
type ResponseGenChallengeData struct {
|
||||
EffectiveSeconds int `json:"effectiveSeconds"`
|
||||
ChallengeID string `json:"challengeId"`
|
||||
ChallengeCode string `json:"challengeCode"`
|
||||
}
|
||||
|
||||
func GenChallengeData(tya *tienyik.AES, cli *hcli.Client) (*ResponseGenChallengeData, error) {
|
||||
resp, err := cli.Post(
|
||||
textio.API(), textio.ContenTypeJSON,
|
||||
strings.NewReader("{}"),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return hson.Unmarshal[*ResponseGenChallengeData](tya, resp.Body)
|
||||
}
|
||||
|
||||
type RequestLogin struct {
|
||||
UserAccount string `form:"userAccount"`
|
||||
Password string `form:"password"`
|
||||
SHA256Password string `form:"sha256Password"`
|
||||
ChallengeID string `form:"challengeId"`
|
||||
DeviceCode string `form:"deviceCode"`
|
||||
DeviceName string `form:"deviceName"`
|
||||
DeviceType string `form:"deviceType"`
|
||||
DeviceModel string `form:"deviceModel"`
|
||||
AppVersion string `form:"appVersion"`
|
||||
SysVersion string `form:"sysVersion"`
|
||||
ClientVersion string `form:"clientVersion"`
|
||||
}
|
||||
|
||||
type ResponseLogin struct {
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
UserID int64 `json:"userId"`
|
||||
UserEid string `json:"userEid"`
|
||||
UserName string `json:"userName"`
|
||||
UserAccount string `json:"userAccount"`
|
||||
Email *string `json:"email"`
|
||||
Mobilephone string `json:"mobilephone"`
|
||||
TenantID int64 `json:"tenantId"`
|
||||
SecretKey string `json:"secretKey"`
|
||||
DeviceType string `json:"deviceType"`
|
||||
TenantName string `json:"tenantName"`
|
||||
BondedDevice bool `json:"bondedDevice"`
|
||||
RealNameStatus int64 `json:"realNameStatus"`
|
||||
HasPassword int64 `json:"hasPassword"`
|
||||
PID *string `json:"pid"`
|
||||
NeedSmsValidate bool `json:"needSmsValidate"`
|
||||
NeedUpdatePassword bool `json:"needUpdatePassword"`
|
||||
ForceUpdateInitialPwd bool `json:"forceUpdateInitialPwd"`
|
||||
AdminUser bool `json:"adminUser"`
|
||||
LoginNotify *string `json:"loginNotify"`
|
||||
CommonLoginReqHeader string `json:"commonLoginReqHeader"`
|
||||
RecordSn bool `json:"recordSn"`
|
||||
Token *string `json:"token"`
|
||||
TwoFaValidateType *string `json:"twoFaValidateType"`
|
||||
Random *string `json:"random"`
|
||||
NeedBindVirtualMfa *bool `json:"needBindVirtualMfa"`
|
||||
Tryout *string `json:"tryout"`
|
||||
CtqEncID *string `json:"ctqEncId"`
|
||||
}
|
||||
|
||||
func (r *ResponseLogin) SetClient(cli *hcli.Client) {
|
||||
cli.Tenantid = strconv.FormatInt(r.TenantID, 10)
|
||||
cli.Usereid = r.UserEid
|
||||
}
|
||||
|
||||
func Login(tya *tienyik.AES, cli *hcli.Client, r *RequestLogin) (*ResponseLogin, error) {
|
||||
resp, err := cli.Post(
|
||||
textio.API(), textio.ContenTypeForm,
|
||||
bytes.NewReader(horm.Marshal(tya, r)),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return hson.Unmarshal[*ResponseLogin](tya, resp.Body)
|
||||
}
|
||||
|
||||
50
api/auth/client/qrCode.go
Normal file
50
api/auth/client/qrCode.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/fumiama/tienyik"
|
||||
"github.com/fumiama/tienyik/hcli"
|
||||
"github.com/fumiama/tienyik/internal/hson"
|
||||
"github.com/fumiama/tienyik/internal/textio"
|
||||
)
|
||||
|
||||
type ResponseGenData struct {
|
||||
QrCodeId string `json:"qrCodeId"`
|
||||
QrCodeEndpoint *string `json:"qrCodeEndpoint"`
|
||||
ServerHost string `json:"serverHost"`
|
||||
}
|
||||
|
||||
func GenData(tya *tienyik.AES, cli *hcli.Client) (*ResponseGenData, error) {
|
||||
resp, err := cli.Post(textio.API(), textio.ContenTypeForm, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return hson.Unmarshal[*ResponseGenData](tya, resp.Body)
|
||||
}
|
||||
|
||||
type ResponseGetStatusData struct {
|
||||
CodeId string `json:"codeId"`
|
||||
CodeStatus string `json:"codeStatus"`
|
||||
LoginToken *string `json:"loginToken"`
|
||||
ClientCustomData *string `json:"clientCustomData"`
|
||||
SupplementData *string `json:"supplementData"`
|
||||
}
|
||||
|
||||
func GetStatus(tya *tienyik.AES, cli *hcli.Client, qrCodeId string) (*ResponseGetStatusData, error) {
|
||||
u, err := url.Parse(textio.API())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q := u.Query()
|
||||
q.Set("qrCodeId", qrCodeId)
|
||||
u.RawQuery = tya.EUrlParams(q)
|
||||
|
||||
resp, err := cli.Get(u.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return hson.Unmarshal[*ResponseGetStatusData](tya, resp.Body)
|
||||
}
|
||||
18
api/auth/client/qrCode_test.go
Normal file
18
api/auth/client/qrCode_test.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/fumiama/tienyik/hcli"
|
||||
)
|
||||
|
||||
func TestGenData(t *testing.T) {
|
||||
r, err := GenData(nil, hcli.NewClient())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(r)
|
||||
if r.QrCodeId == "" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package auth
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"encoding/base64"
|
||||
"testing"
|
||||
|
||||
"github.com/fumiama/tienyik"
|
||||
@@ -32,23 +31,8 @@ func TestNegotiationEncKey(t *testing.T) {
|
||||
t.Logf("EncData: %s", r.EncData)
|
||||
t.Logf("EncKey: %s", r.EncKey)
|
||||
|
||||
v, err := base64.StdEncoding.DecodeString(r.EncKey)
|
||||
_, err = r.Unwrap(tyr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
aesk, err := tyr.Decrypt(v)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(string(aesk))
|
||||
|
||||
v, err = base64.StdEncoding.DecodeString(r.EncData)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
v, err = tienyik.NewAES([]byte(aesk)).Decrypt(v)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(string(v))
|
||||
}
|
||||
|
||||
32
api/cdserv/client.go
Normal file
32
api/cdserv/client.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package cdserv
|
||||
|
||||
import (
|
||||
"github.com/fumiama/tienyik/hcli"
|
||||
"github.com/fumiama/tienyik/internal/hson"
|
||||
"github.com/fumiama/tienyik/internal/textio"
|
||||
)
|
||||
|
||||
type GlobalSwitches struct {
|
||||
BodyMsgEType []string `json:"bodyMsgEType"`
|
||||
PasswordRulesEnable bool `json:"passwordRulesEnable"`
|
||||
}
|
||||
|
||||
type ResponseGetServData struct {
|
||||
GlobalSwitches GlobalSwitches `json:"globalSwitches"`
|
||||
ServerNodeId string `json:"serverNodeId"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
NetAccessType int `json:"netAccessType"`
|
||||
}
|
||||
|
||||
func (r *ResponseGetServData) SetClient(cli *hcli.Client) {
|
||||
cli.Servernode = r.ServerNodeId
|
||||
}
|
||||
|
||||
func GetServData() (*ResponseGetServData, error) {
|
||||
resp, err := hcli.NoClient.Get(textio.API())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return hson.Unmarshal[*ResponseGetServData](nil, resp.Body)
|
||||
}
|
||||
14
api/cdserv/client_test.go
Normal file
14
api/cdserv/client_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package cdserv
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestGetServData(t *testing.T) {
|
||||
r, err := GetServData()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(r)
|
||||
if len(r.GlobalSwitches.BodyMsgEType) == 0 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
31
cfg.go
Normal file
31
cfg.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package tienyik
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const Version = "103010001"
|
||||
|
||||
const (
|
||||
DeviceTypePC = "25"
|
||||
DeviceTypeMAC = "45"
|
||||
DeviceTypeWEB = "60"
|
||||
)
|
||||
|
||||
const (
|
||||
AppModelTOC = "1"
|
||||
AppModelTOB = "2"
|
||||
AppModelPHONE = "3"
|
||||
)
|
||||
|
||||
func NewDeviceCode() string {
|
||||
sb := &strings.Builder{}
|
||||
sb.WriteString("web_")
|
||||
enc := base64.NewEncoder(base64.RawURLEncoding, sb)
|
||||
io.CopyN(enc, rand.Reader, (32/6+1)*8)
|
||||
enc.Close()
|
||||
return sb.String()[:4+32]
|
||||
}
|
||||
7
go.mod
7
go.mod
@@ -5,10 +5,11 @@ go 1.24.4
|
||||
require (
|
||||
github.com/fumiama/go-base16384 v1.7.1
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
golang.org/x/net v0.28.0
|
||||
)
|
||||
|
||||
require (
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
github.com/stretchr/testify v1.8.0 // indirect
|
||||
golang.org/x/sys v0.23.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
)
|
||||
|
||||
12
go.sum
12
go.sum
@@ -8,13 +8,19 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
80
hcli/cli.go
Normal file
80
hcli/cli.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package hcli
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
base14 "github.com/fumiama/go-base16384"
|
||||
"github.com/fumiama/tienyik"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
var NoClient = (*Client)(nil)
|
||||
|
||||
// DefaultClient is the default HTTP2 client.
|
||||
var DefaultClient = http.Client{
|
||||
Transport: &http2.Transport{},
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
rcnt uintptr
|
||||
Appmodel string
|
||||
Devicecode string
|
||||
Devicetype string
|
||||
Servernode string
|
||||
Tenantid string
|
||||
Usereid string
|
||||
Version string
|
||||
}
|
||||
|
||||
func NewClient() *Client {
|
||||
return &Client{
|
||||
Appmodel: tienyik.AppModelTOB,
|
||||
Devicecode: tienyik.NewDeviceCode(),
|
||||
Devicetype: tienyik.DeviceTypeWEB,
|
||||
Version: tienyik.Version,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) setHeaders(req *http.Request) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(c).Elem()
|
||||
t := v.Type()
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
if !field.IsExported() {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldValue := v.Field(i)
|
||||
|
||||
if fieldValue.Kind() == reflect.String {
|
||||
req.Header.Set(
|
||||
base14.DecodeString("廝呲舀㴄")+field.Name,
|
||||
fieldValue.String(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if c.Appmodel != "" {
|
||||
ts := time.Now().UnixMilli()
|
||||
timestamp := strconv.FormatInt(ts, 10)
|
||||
requestid := strconv.FormatUint(
|
||||
uint64(atomic.AddUintptr(&c.rcnt, 1))+uint64(ts), 10,
|
||||
)
|
||||
|
||||
req.Header.Set(base14.DecodeString("廝呲草獱歙攷徥爀㴆"), requestid)
|
||||
req.Header.Set(base14.DecodeString("廝呲荑睭杜蕆厵縀㴆"), timestamp)
|
||||
}
|
||||
|
||||
if c.Servernode != "" {
|
||||
//TODO: gensign
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,12 @@ import (
|
||||
base14 "github.com/fumiama/go-base16384"
|
||||
)
|
||||
|
||||
func setCommonHeaders(req *http.Request) {
|
||||
func setCommonHeaders(req *http.Request, contentType string) {
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header.Set("Pragma", "no-cache")
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
if contentType != "" {
|
||||
req.Header.Set("Content-Type", contentType)
|
||||
}
|
||||
req.Header.Set("Origin", base14.DecodeString("栝啇俌蠯姜吲融艹歛烦宸㴅"))
|
||||
req.Header.Set("Referer", base14.DecodeString("栝啇俌蠯姜吲融艹歛烦宸紀㴆"))
|
||||
req.Header.Set(
|
||||
@@ -19,47 +21,52 @@ func setCommonHeaders(req *http.Request) {
|
||||
)
|
||||
}
|
||||
|
||||
func Get(path string) (resp *http.Response, err error) {
|
||||
func (cli *Client) Get(path string) (resp *http.Response, err error) {
|
||||
req, err := http.NewRequest(http.MethodGet, ep(path), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setCommonHeaders(req)
|
||||
return http.DefaultClient.Do(req)
|
||||
setCommonHeaders(req, "")
|
||||
cli.setHeaders(req)
|
||||
return DefaultClient.Do(req)
|
||||
}
|
||||
|
||||
func Post(path string, body io.Reader) (resp *http.Response, err error) {
|
||||
func (cli *Client) Post(path string, contentType string, body io.Reader) (resp *http.Response, err error) {
|
||||
req, err := http.NewRequest(http.MethodPost, ep(path), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setCommonHeaders(req)
|
||||
return http.DefaultClient.Do(req)
|
||||
setCommonHeaders(req, contentType)
|
||||
cli.setHeaders(req)
|
||||
return DefaultClient.Do(req)
|
||||
}
|
||||
|
||||
func Put(path string, body io.Reader) (resp *http.Response, err error) {
|
||||
func (cli *Client) Put(path string, contentType string, body io.Reader) (resp *http.Response, err error) {
|
||||
req, err := http.NewRequest(http.MethodPut, ep(path), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setCommonHeaders(req)
|
||||
return http.DefaultClient.Do(req)
|
||||
setCommonHeaders(req, contentType)
|
||||
cli.setHeaders(req)
|
||||
return DefaultClient.Do(req)
|
||||
}
|
||||
|
||||
func Delete(path string) (resp *http.Response, err error) {
|
||||
func (cli *Client) Delete(path string) (resp *http.Response, err error) {
|
||||
req, err := http.NewRequest(http.MethodDelete, ep(path), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setCommonHeaders(req)
|
||||
return http.DefaultClient.Do(req)
|
||||
setCommonHeaders(req, "")
|
||||
cli.setHeaders(req)
|
||||
return DefaultClient.Do(req)
|
||||
}
|
||||
|
||||
func Patch(path string, body io.Reader) (resp *http.Response, err error) {
|
||||
func (cli *Client) Patch(path string, contentType string, body io.Reader) (resp *http.Response, err error) {
|
||||
req, err := http.NewRequest(http.MethodPatch, ep(path), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setCommonHeaders(req)
|
||||
return http.DefaultClient.Do(req)
|
||||
setCommonHeaders(req, contentType)
|
||||
cli.setHeaders(req)
|
||||
return DefaultClient.Do(req)
|
||||
}
|
||||
40
http.go
Normal file
40
http.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package tienyik
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
|
||||
"github.com/fumiama/tienyik/internal/textio"
|
||||
)
|
||||
|
||||
func (tya *AES) EUrlParams(params url.Values) string {
|
||||
if tya == nil {
|
||||
return params.Encode()
|
||||
}
|
||||
return url.Values{
|
||||
textio.FuncName(1, true): {textio.BytesToString(tya.Encrypt(
|
||||
textio.StringToBytes(params.Encode()),
|
||||
))},
|
||||
}.Encode()
|
||||
}
|
||||
|
||||
func (tya *AES) ParseQuery(eparams string) (url.Values, error) {
|
||||
if tya == nil {
|
||||
return url.ParseQuery(eparams)
|
||||
}
|
||||
q, err := url.ParseQuery(eparams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(q) != 1 {
|
||||
return nil, errors.New("len(q) must be 1")
|
||||
}
|
||||
for _, v := range q {
|
||||
dec, err := tya.Decrypt(textio.StringToBytes(v[0]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return url.ParseQuery(textio.BytesToString(dec))
|
||||
}
|
||||
panic("unexpected")
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
package textio
|
||||
package tienyik
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/fumiama/tienyik"
|
||||
)
|
||||
|
||||
func TestEUrlParams(t *testing.T) {
|
||||
@@ -21,11 +19,12 @@ func TestEUrlParams(t *testing.T) {
|
||||
binary.BigEndian.PutUint32(key[i*4:(i+1)*4], k)
|
||||
}
|
||||
t.Log(string(key[:])) // wxdispbis8txuueo26ffs2veqs18sism
|
||||
tya := tienyik.NewAES(key[:])
|
||||
params := EUrlParams(&tya, url.Values{
|
||||
tya := NewAES(key[:])
|
||||
params := tya.EUrlParams(url.Values{
|
||||
"moduleCode": {"DESKTOP_MSGCENTER"},
|
||||
})
|
||||
q, err := ParseQuery(&tya, params)
|
||||
t.Log(params)
|
||||
q, err := tya.ParseQuery(params)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -48,7 +47,7 @@ func TestEUrlParamsMultiple(t *testing.T) {
|
||||
for i, k := range rawkey {
|
||||
binary.BigEndian.PutUint32(key[i*4:(i+1)*4], k)
|
||||
}
|
||||
tya := tienyik.NewAES(key[:])
|
||||
tya := NewAES(key[:])
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -103,8 +102,8 @@ func TestEUrlParamsMultiple(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
params := EUrlParams(&tya, tc.params)
|
||||
q, err := ParseQuery(&tya, params)
|
||||
params := tya.EUrlParams(tc.params)
|
||||
q, err := tya.ParseQuery(params)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
35
internal/horm/req.go
Normal file
35
internal/horm/req.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package horm
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
|
||||
"github.com/fumiama/tienyik"
|
||||
"github.com/fumiama/tienyik/internal/textio"
|
||||
)
|
||||
|
||||
func Marshal(tya *tienyik.AES, x any) []byte {
|
||||
q := url.Values{}
|
||||
v := reflect.ValueOf(x).Elem()
|
||||
t := v.Type()
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Field(i)
|
||||
fieldType := t.Field(i)
|
||||
|
||||
formTag := fieldType.Tag.Get("form")
|
||||
if formTag == "" || formTag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
if field.Kind() == reflect.String {
|
||||
q.Set(formTag, field.String())
|
||||
}
|
||||
}
|
||||
|
||||
s := q.Encode()
|
||||
if tya != nil {
|
||||
return tya.Encrypt(textio.StringToBytes(s))
|
||||
}
|
||||
return textio.StringToBytes(s)
|
||||
}
|
||||
@@ -2,12 +2,18 @@ package hson
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/fumiama/tienyik"
|
||||
"github.com/fumiama/tienyik/internal/log"
|
||||
"github.com/fumiama/tienyik/internal/op"
|
||||
)
|
||||
|
||||
type reqbody struct {
|
||||
EData string `json:"edata"`
|
||||
}
|
||||
|
||||
func Marshal(tya *tienyik.AES, v any) []byte {
|
||||
w := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
err := json.NewEncoder(w).Encode(v)
|
||||
@@ -16,7 +22,9 @@ func Marshal(tya *tienyik.AES, v any) []byte {
|
||||
}
|
||||
log.Debugln("Marshal JSON:", w.String())
|
||||
if tya != nil {
|
||||
return tya.Encrypt(w.Bytes())
|
||||
return tya.Encrypt(op.Must(json.Marshal(&reqbody{
|
||||
EData: base64.StdEncoding.EncodeToString(w.Bytes()),
|
||||
})))
|
||||
}
|
||||
return w.Bytes()
|
||||
}
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
package textio
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/fumiama/tienyik"
|
||||
)
|
||||
|
||||
func API() string {
|
||||
@@ -42,29 +38,3 @@ func API() string {
|
||||
sb.WriteString(p[1:])
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func EUrlParams(tya *tienyik.AES, params url.Values) string {
|
||||
return url.Values{
|
||||
FuncName(1, true): {BytesToString(tya.Encrypt(
|
||||
StringToBytes(params.Encode()),
|
||||
))},
|
||||
}.Encode()
|
||||
}
|
||||
|
||||
func ParseQuery(tya *tienyik.AES, eparams string) (url.Values, error) {
|
||||
q, err := url.ParseQuery(eparams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(q) != 1 {
|
||||
return nil, errors.New("len(q) must be 1")
|
||||
}
|
||||
for _, v := range q {
|
||||
dec, err := tya.Decrypt(StringToBytes(v[0]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return url.ParseQuery(BytesToString(dec))
|
||||
}
|
||||
panic("unexpected")
|
||||
}
|
||||
|
||||
6
internal/textio/http.go
Normal file
6
internal/textio/http.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package textio
|
||||
|
||||
const (
|
||||
ContenTypeForm = "application/x-www-form-urlencoded"
|
||||
ContenTypeJSON = "application/json"
|
||||
)
|
||||
25
sha256.go
Normal file
25
sha256.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package tienyik
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
func ChallengePassword(pwd string, chlg string) string {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(pwd))
|
||||
h.Write([]byte(chlg))
|
||||
var sum [sha256.Size]byte
|
||||
return hex.EncodeToString(h.Sum(sum[:0]))
|
||||
}
|
||||
|
||||
func ChallengeSHA256Password(pwd string, chlg string) string {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(pwd))
|
||||
var sum [sha256.Size]byte
|
||||
s := hex.EncodeToString(h.Sum(sum[:0]))
|
||||
h.Reset()
|
||||
h.Write([]byte(s))
|
||||
h.Write([]byte(chlg))
|
||||
return hex.EncodeToString(h.Sum(sum[:0]))
|
||||
}
|
||||
Reference in New Issue
Block a user