Compare commits
8 commits
main
...
v0.10.3-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80e15d5be7 | ||
|
|
868ca0132e | ||
|
|
5edc9e809f | ||
|
|
9649a1d234 | ||
|
|
fbd3fc4c3c | ||
|
|
b96e519981 | ||
|
|
d7d3d832cb | ||
|
|
3511a4bd73 |
9 changed files with 484 additions and 12 deletions
3
.github/workflows/unit-test.yml
vendored
3
.github/workflows/unit-test.yml
vendored
|
|
@ -85,7 +85,7 @@ jobs:
|
|||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ${{ env.REPO_GOU }}
|
||||
ref: dc3d98411f61e21cf775e4c82d92d5ac2acfc03c
|
||||
ref: v0.10.2-locked
|
||||
path: gou
|
||||
|
||||
- name: Checkout V8Go
|
||||
|
|
@ -99,6 +99,7 @@ jobs:
|
|||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: yaoapp/yao-dev-app
|
||||
ref: fef08943afc6ff91ed7a9a44559118ad40074e6b
|
||||
path: app
|
||||
|
||||
- name: Move Kun, Xun, Gou, V8Go
|
||||
|
|
|
|||
18
Makefile
18
Makefile
|
|
@ -171,10 +171,10 @@ artifacts-linux: clean
|
|||
export NODE_ENV=production
|
||||
rm -f ../xgen-v1.0/pnpm-lock.yaml
|
||||
echo "BASE=__yao_admin_root" > ../xgen-v1.0/packages/xgen/.env
|
||||
cd ../xgen-v1.0 && pnpm install && pnpm run build
|
||||
cd ../xgen-v1.0 && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
# Setup UI
|
||||
cd ../xgen-v1.0/packages/setup && pnpm install && pnpm run build
|
||||
cd ../xgen-v1.0/packages/setup && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
# Init Application
|
||||
cd ../yao-init rm -rf .git
|
||||
|
|
@ -197,6 +197,7 @@ artifacts-linux: clean
|
|||
sed -ie "s/const PRVERSION = \"DEV\"/const PRVERSION = \"${COMMIT}-${NOW}\"/g" share/const.go
|
||||
|
||||
# Making artifacts
|
||||
go mod tidy
|
||||
mkdir -p dist
|
||||
CGO_ENABLED=1 CGO_LDFLAGS="-static" GOOS=linux GOARCH=amd64 go build -v -o dist/yao-${VERSION}-linux-amd64
|
||||
CGO_ENABLED=1 CGO_LDFLAGS="-static" GOOS=linux GOARCH=arm64 CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ go build -v -o dist/yao-${VERSION}-linux-arm64
|
||||
|
|
@ -221,10 +222,10 @@ artifacts-macos: clean
|
|||
export NODE_ENV=production
|
||||
rm -f ../xgen-v1.0/pnpm-lock.yaml
|
||||
echo "BASE=__yao_admin_root" > ../xgen-v1.0/packages/xgen/.env
|
||||
cd ../xgen-v1.0 && pnpm install && pnpm run build
|
||||
cd ../xgen-v1.0 && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
# Setup UI
|
||||
cd ../xgen-v1.0/packages/setup && pnpm install && pnpm run build
|
||||
cd ../xgen-v1.0/packages/setup && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
# Init Application
|
||||
cd ../yao-init rm -rf .git
|
||||
|
|
@ -247,6 +248,7 @@ artifacts-macos: clean
|
|||
sed -ie "s/const PRVERSION = \"DEV\"/const PRVERSION = \"${COMMIT}-${NOW}\"/g" share/const.go
|
||||
|
||||
# Making artifacts
|
||||
go mod tidy
|
||||
mkdir -p dist
|
||||
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -v -o dist/yao-${VERSION}-darwin-amd64
|
||||
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 go build -v -o dist/yao-${VERSION}-darwin-arm64
|
||||
|
|
@ -299,10 +301,10 @@ release: clean
|
|||
git clone https://github.com/YaoApp/xgen.git .tmp/xgen/v1.0
|
||||
# cd .tmp/xgen/v1.0 && git checkout 5002c3fded585aaa69a4366135b415ea3234964e
|
||||
echo "BASE=__yao_admin_root" > .tmp/xgen/v1.0/packages/xgen/.env
|
||||
cd .tmp/xgen/v1.0 && pnpm install && pnpm run build
|
||||
cd .tmp/xgen/v1.0 && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
# Setup UI
|
||||
cd .tmp/xgen/v1.0/packages/setup && pnpm install && pnpm run build
|
||||
cd .tmp/xgen/v1.0/packages/setup && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
|
||||
# Checkout init
|
||||
|
|
@ -353,10 +355,10 @@ linux-release: clean
|
|||
git clone https://github.com/YaoApp/xgen.git .tmp/xgen/v1.0
|
||||
rm -f .tmp/xgen/v1.0/pnpm-lock.yaml
|
||||
echo "BASE=__yao_admin_root" > .tmp/xgen/v1.0/packages/xgen/.env
|
||||
cd .tmp/xgen/v1.0 && pnpm install && pnpm run build
|
||||
cd .tmp/xgen/v1.0 && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
# Setup UI
|
||||
cd .tmp/xgen/v1.0/packages/setup && pnpm install && pnpm run build
|
||||
cd .tmp/xgen/v1.0/packages/setup && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
|
||||
# Checkout init
|
||||
|
|
|
|||
58
crypto/aes.go
Normal file
58
crypto/aes.go
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Base64AESEncode AES encode
|
||||
func Base64AESEncode(key []byte, text string) (string, error) {
|
||||
|
||||
plaintext := []byte(text)
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// The IV needs to be unique, but not secure. Therefore it's common to
|
||||
// include it at the beginning of the ciphertext.
|
||||
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
|
||||
iv := ciphertext[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
|
||||
|
||||
// convert to base64
|
||||
return base64.StdEncoding.EncodeToString(ciphertext), nil
|
||||
}
|
||||
|
||||
// Base64AESDecode AES decode
|
||||
func Base64AESDecode(key []byte, cryptoText string) (string, error) {
|
||||
ciphertext, _ := base64.StdEncoding.DecodeString(cryptoText)
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// The IV needs to be unique, but not secure. Therefore it's common to
|
||||
// include it at the beginning of the ciphertext.
|
||||
if len(ciphertext) < aes.BlockSize {
|
||||
return "", fmt.Errorf("ciphertext too short")
|
||||
}
|
||||
iv := ciphertext[:aes.BlockSize]
|
||||
ciphertext = ciphertext[aes.BlockSize:]
|
||||
|
||||
stream := cipher.NewCFBDecrypter(block, iv)
|
||||
|
||||
// XORKeyStream can work in-place if the two arguments are the same.
|
||||
stream.XORKeyStream(ciphertext, ciphertext)
|
||||
return fmt.Sprintf("%s", ciphertext), nil
|
||||
}
|
||||
37
crypto/aes_test.go
Normal file
37
crypto/aes_test.go
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
)
|
||||
|
||||
func TestBase64AES(t *testing.T) {
|
||||
|
||||
originalText := "encrypt this golang"
|
||||
key := []byte("example key 1234")
|
||||
|
||||
// encrypt value to base64
|
||||
cryptoText, err := Base64AESEncode(key, originalText)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// encrypt base64 crypto to original value
|
||||
text, err := Base64AESDecode(key, cryptoText)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, "encrypt this golang", text)
|
||||
}
|
||||
|
||||
func TestBase64AESProcess(t *testing.T) {
|
||||
|
||||
args := []interface{}{"example key 1234", "encrypt this golang"}
|
||||
cryptoText := gou.NewProcess("yao.crypto.AESBase64Encode", args...).Run()
|
||||
|
||||
args = []interface{}{"example key 1234", cryptoText}
|
||||
text := gou.NewProcess("yao.crypto.AESBase64Decode", args...).Run()
|
||||
assert.Equal(t, "encrypt this golang", text)
|
||||
}
|
||||
|
|
@ -8,6 +8,9 @@ import (
|
|||
func init() {
|
||||
gou.RegisterProcessHandler("yao.crypto.hash", ProcessHash) // deprecated → crypto.Hash
|
||||
gou.RegisterProcessHandler("yao.crypto.hmac", ProcessHmac) // deprecated → crypto.Hash
|
||||
gou.RegisterProcessHandler("yao.crypto.AESBase64Encode", processBase64AESEncode)
|
||||
gou.RegisterProcessHandler("yao.crypto.AESBase64Decode", processBase64AESDecode)
|
||||
gou.RegisterProcessHandler("yao.crypto.WeworkDecrypt", processWeworkDecrypt)
|
||||
|
||||
gou.AliasProcess("yao.crypto.hash", "crypto.Hash")
|
||||
gou.AliasProcess("yao.crypto.hmac", "crypto.Hmac")
|
||||
|
|
@ -60,3 +63,44 @@ func ProcessHmac(process *gou.Process) interface{} {
|
|||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func processBase64AESEncode(process *gou.Process) interface{} {
|
||||
process.ValidateArgNums(2)
|
||||
key := process.ArgsString(0)
|
||||
value := process.ArgsString(1)
|
||||
res, err := Base64AESEncode([]byte(key), value)
|
||||
if err != nil {
|
||||
exception.New("error: %s value: %s", 400, err, value).Throw()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func processBase64AESDecode(process *gou.Process) interface{} {
|
||||
process.ValidateArgNums(2)
|
||||
key := process.ArgsString(0)
|
||||
value := process.ArgsString(1)
|
||||
res, err := Base64AESDecode([]byte(key), value)
|
||||
if err != nil {
|
||||
exception.New("error: %s value: %s", 400, err, value).Throw()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func processWeworkDecrypt(process *gou.Process) interface{} {
|
||||
|
||||
process.ValidateArgNums(2)
|
||||
encodingAESKey := process.ArgsString(0)
|
||||
msgEncrypt := process.ArgsString(1)
|
||||
parseXML := false
|
||||
|
||||
if process.NumOfArgsIs(3) {
|
||||
parseXML = process.ArgsBool(2)
|
||||
}
|
||||
|
||||
res, err := WeworkDecrypt(encodingAESKey, msgEncrypt, parseXML)
|
||||
if err != nil {
|
||||
exception.New("error: %s msgEncrypt: %s", 400, err, msgEncrypt).Throw()
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
|
|
|||
81
crypto/wework.go
Normal file
81
crypto/wework.go
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// WeworkDecrypt wework msg Decrypt
|
||||
func WeworkDecrypt(encodingAESKey string, msgEncrypt string, parse bool) (map[string]interface{}, error) {
|
||||
|
||||
var err error
|
||||
aseKey, err := base64.StdEncoding.DecodeString(encodingAESKey + "=")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ciphertext, err := base64.StdEncoding.DecodeString(msgEncrypt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
randMsg, err := aesDecrypt(ciphertext, aseKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
content := randMsg[16:]
|
||||
buf := bytes.NewBuffer(content[0:4])
|
||||
var len int32
|
||||
binary.Read(buf, binary.BigEndian, &len)
|
||||
msg := content[4 : len+4]
|
||||
receiveid := content[len+4:]
|
||||
|
||||
data := map[string]interface{}{}
|
||||
if parse {
|
||||
data, err = parseXML(string(msg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"message": string(msg),
|
||||
"data": data,
|
||||
"receiveid": string(receiveid),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseXML(data string) (map[string]interface{}, error) {
|
||||
|
||||
decoder := NewDecoder(strings.NewReader(data))
|
||||
result, err := decoder.Decode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func aesDecrypt(crypted, key []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockSize := block.BlockSize()
|
||||
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
|
||||
origData := make([]byte, len(crypted))
|
||||
blockMode.CryptBlocks(origData, crypted)
|
||||
origData = pckS5UnPadding(origData)
|
||||
return origData, nil
|
||||
}
|
||||
|
||||
func pckS5UnPadding(origData []byte) []byte {
|
||||
length := len(origData)
|
||||
unpadding := int(origData[length-1])
|
||||
return origData[:(length - unpadding)]
|
||||
}
|
||||
61
crypto/wework_test.go
Normal file
61
crypto/wework_test.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/maps"
|
||||
)
|
||||
|
||||
func TestWework(t *testing.T) {
|
||||
|
||||
msgEncrypt := "meqbMyPr58hNy0j0YDdG9UT60UJZSh/tb3KOZt3z2SCKr6uvmSLbEnUCM89iFXS0BLWn11FOrD/xXsGUlVUSBw=="
|
||||
encodingAESKey := "RhH75tStMzrH8bMxkTw8BrBfr0ZWULL5himUaRWCs7H"
|
||||
|
||||
res, err := WeworkDecrypt(encodingAESKey, msgEncrypt, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, "8446271472585838141", res["message"])
|
||||
assert.Equal(t, "wwe146299c731e6301", res["receiveid"])
|
||||
}
|
||||
|
||||
func TestWeworkProcess(t *testing.T) {
|
||||
|
||||
msgEncrypt := "meqbMyPr58hNy0j0YDdG9UT60UJZSh/tb3KOZt3z2SCKr6uvmSLbEnUCM89iFXS0BLWn11FOrD/xXsGUlVUSBw=="
|
||||
encodingAESKey := "RhH75tStMzrH8bMxkTw8BrBfr0ZWULL5himUaRWCs7H"
|
||||
|
||||
args := []interface{}{encodingAESKey, msgEncrypt}
|
||||
res := gou.NewProcess("yao.crypto.WeworkDecrypt", args...).Run().(map[string]interface{})
|
||||
|
||||
assert.Equal(t, "8446271472585838141", res["message"])
|
||||
assert.Equal(t, "wwe146299c731e6301", res["receiveid"])
|
||||
}
|
||||
|
||||
func TestWeworkParseXML(t *testing.T) {
|
||||
|
||||
xml := `
|
||||
<xml>
|
||||
<ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName>
|
||||
<FromUserName><![CDATA[mycreate]]></FromUserName>
|
||||
<CreateTime>1409659813</CreateTime>
|
||||
<MsgType><![CDATA[text]]></MsgType>
|
||||
<Content><![CDATA[hello]]></Content>
|
||||
<MsgId>4561255354251345929</MsgId>
|
||||
<AgentID>218</AgentID>
|
||||
<Nest>
|
||||
<Id>111</Id>
|
||||
</Nest>
|
||||
</xml>`
|
||||
|
||||
data, err := parseXML(xml)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
res := maps.Of(data).Dot()
|
||||
assert.Equal(t, "218", res.Get("xml.AgentID"))
|
||||
assert.Equal(t, "111", res.Get("xml.Nest.Id"))
|
||||
}
|
||||
180
crypto/xml.go
Normal file
180
crypto/xml.go
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
attrPrefix = "@"
|
||||
textPrefix = "#text"
|
||||
)
|
||||
|
||||
var (
|
||||
//ErrInvalidDocument invalid document err
|
||||
ErrInvalidDocument = errors.New("invalid document")
|
||||
|
||||
//ErrInvalidRoot data at the root level is invalid err
|
||||
ErrInvalidRoot = errors.New("data at the root level is invalid")
|
||||
)
|
||||
|
||||
type node struct {
|
||||
Parent *node
|
||||
Value map[string]interface{}
|
||||
Attrs []xml.Attr
|
||||
Label string
|
||||
Space string
|
||||
Text string
|
||||
HasMany bool
|
||||
}
|
||||
|
||||
// Decoder instance
|
||||
type Decoder struct {
|
||||
r io.Reader
|
||||
attrPrefix string
|
||||
textPrefix string
|
||||
}
|
||||
|
||||
// NewDecoder create new decoder instance
|
||||
func NewDecoder(reader io.Reader) *Decoder {
|
||||
return NewDecoderWithPrefix(reader, attrPrefix, textPrefix)
|
||||
}
|
||||
|
||||
// NewDecoderWithPrefix create new decoder instance with custom attribute prefix and text prefix
|
||||
func NewDecoderWithPrefix(reader io.Reader, attrPrefix, textPrefix string) *Decoder {
|
||||
return &Decoder{r: reader, attrPrefix: attrPrefix, textPrefix: textPrefix}
|
||||
}
|
||||
|
||||
// Decode xml string to map[string]interface{}
|
||||
func (d *Decoder) Decode() (map[string]interface{}, error) {
|
||||
decoder := xml.NewDecoder(d.r)
|
||||
n := &node{}
|
||||
stack := make([]*node, 0)
|
||||
|
||||
for {
|
||||
token, err := decoder.Token()
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if token == nil {
|
||||
break
|
||||
}
|
||||
|
||||
switch tok := token.(type) {
|
||||
case xml.StartElement:
|
||||
{
|
||||
label := tok.Name.Local
|
||||
if tok.Name.Space != "" {
|
||||
label = fmt.Sprintf("%s:%s", strings.ToLower(path.Base(tok.Name.Space)), tok.Name.Local)
|
||||
}
|
||||
n = &node{
|
||||
Label: label,
|
||||
Space: tok.Name.Space,
|
||||
Parent: n,
|
||||
Value: map[string]interface{}{label: map[string]interface{}{}},
|
||||
Attrs: tok.Attr,
|
||||
}
|
||||
|
||||
setAttrs(n, &tok, d.attrPrefix)
|
||||
stack = append(stack, n)
|
||||
|
||||
if n.Parent != nil {
|
||||
n.Parent.HasMany = true
|
||||
}
|
||||
}
|
||||
|
||||
case xml.CharData:
|
||||
data := strings.TrimSpace(string(tok))
|
||||
if len(stack) > 0 {
|
||||
stack[len(stack)-1].Text = data
|
||||
} else if len(data) > 0 {
|
||||
return nil, ErrInvalidRoot
|
||||
}
|
||||
|
||||
case xml.EndElement:
|
||||
{
|
||||
length := len(stack)
|
||||
stack, n = stack[:length-1], stack[length-1]
|
||||
|
||||
if !n.HasMany {
|
||||
if len(n.Attrs) > 0 {
|
||||
m := n.Value[n.Label].(map[string]interface{})
|
||||
m[d.textPrefix] = n.Text
|
||||
} else {
|
||||
n.Value[n.Label] = n.Text
|
||||
}
|
||||
}
|
||||
|
||||
if len(stack) == 0 {
|
||||
return n.Value, nil
|
||||
}
|
||||
|
||||
setNodeValue(n)
|
||||
n = n.Parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, ErrInvalidDocument
|
||||
}
|
||||
|
||||
func setAttrs(n *node, tok *xml.StartElement, attrPrefix string) {
|
||||
if len(tok.Attr) > 0 {
|
||||
m := make(map[string]interface{})
|
||||
for _, attr := range tok.Attr {
|
||||
if len(attr.Name.Space) > 0 {
|
||||
m[attrPrefix+attr.Name.Space+":"+attr.Name.Local] = attr.Value
|
||||
} else {
|
||||
m[attrPrefix+attr.Name.Local] = attr.Value
|
||||
}
|
||||
}
|
||||
n.Value[tok.Name.Local] = m
|
||||
}
|
||||
}
|
||||
|
||||
func setNodeValue(n *node) {
|
||||
if v, ok := n.Parent.Value[n.Parent.Label]; ok {
|
||||
m := v.(map[string]interface{})
|
||||
if v, ok = m[n.Label]; ok {
|
||||
switch item := v.(type) {
|
||||
case string:
|
||||
m[n.Label] = []string{item, n.Value[n.Label].(string)}
|
||||
case []string:
|
||||
m[n.Label] = append(item, n.Value[n.Label].(string))
|
||||
case map[string]interface{}:
|
||||
vm := getMap(n)
|
||||
if vm != nil {
|
||||
m[n.Label] = []map[string]interface{}{item, vm}
|
||||
}
|
||||
case []map[string]interface{}:
|
||||
vm := getMap(n)
|
||||
if vm != nil {
|
||||
m[n.Label] = append(item, vm)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m[n.Label] = n.Value[n.Label]
|
||||
}
|
||||
|
||||
} else {
|
||||
n.Parent.Value[n.Parent.Label] = n.Value[n.Label]
|
||||
}
|
||||
}
|
||||
|
||||
func getMap(node *node) map[string]interface{} {
|
||||
if v, ok := node.Value[node.Label]; ok {
|
||||
switch v.(type) {
|
||||
case string:
|
||||
return map[string]interface{}{node.Label: v}
|
||||
case map[string]interface{}:
|
||||
return node.Value[node.Label].(map[string]interface{})
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/sts"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/gou/session"
|
||||
"github.com/yaoapp/kun/any"
|
||||
|
|
@ -33,9 +34,16 @@ func init() {
|
|||
// processUpload 上传文件到本地服务器
|
||||
func processUpload(process *gou.Process) interface{} {
|
||||
process.ValidateArgNums(1)
|
||||
tmpfile, ok := process.Args[0].(xun.UploadFile)
|
||||
if !ok {
|
||||
exception.New("上传文件参数错误", 400, process.Args[0]).Throw()
|
||||
|
||||
var tmpfile xun.UploadFile
|
||||
data, err := jsoniter.Marshal(process.Args[0])
|
||||
if err != nil {
|
||||
exception.New("上传文件参数错误 %s %v", 400, err.Error(), process.Args[0]).Throw()
|
||||
}
|
||||
|
||||
err = jsoniter.Unmarshal(data, &tmpfile)
|
||||
if err != nil {
|
||||
exception.New("上传文件参数错误 %s %v", 400, err.Error(), process.Args[0]).Throw()
|
||||
}
|
||||
|
||||
hash := md5.Sum([]byte(time.Now().Format("20060102-15:04:05")))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue