This commit is contained in:
parent
bf0aaaca8f
commit
94106bb82f
8 changed files with 430 additions and 1 deletions
17
go.mod
17
go.mod
|
@ -5,16 +5,24 @@ go 1.24.2
|
|||
require (
|
||||
git.mstar.dev/mstar/goutils v1.14.2
|
||||
github.com/BurntSushi/toml v1.5.0
|
||||
github.com/PeerDB-io/gluabit32 v1.0.2
|
||||
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9
|
||||
github.com/cosmotek/loguago v1.0.0
|
||||
github.com/go-acme/lego/v4 v4.23.1
|
||||
github.com/go-webauthn/webauthn v0.12.3
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jackc/pgx/v5 v5.7.4
|
||||
github.com/kohkimakimoto/gluatemplate v0.0.0-20160815033744-d9e2c9d6b00f
|
||||
github.com/layeh/gopher-json v0.0.0-20201124131017-552bb3c4c3bf
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/nrednav/cuid2 v1.0.1
|
||||
github.com/pquerna/otp v1.4.0
|
||||
github.com/quic-go/quic-go v0.52.0
|
||||
github.com/rs/xid v1.6.0
|
||||
github.com/rs/zerolog v1.34.0
|
||||
github.com/yaronf/httpsign v0.3.2
|
||||
github.com/yuin/gluare v0.0.0-20170607022532-d7c94f1a80ed
|
||||
github.com/yuin/gopher-lua v1.1.1
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/sys v0.32.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
|
@ -45,6 +53,7 @@ require (
|
|||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.3 // indirect
|
||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||
github.com/lestrrat-go/httprc v1.0.6 // indirect
|
||||
|
@ -54,11 +63,16 @@ require (
|
|||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/miekg/dns v1.1.64 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/multiformats/go-multihash v0.2.3 // indirect
|
||||
github.com/multiformats/go-varint v0.0.6 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/quic-go/quic-go v0.52.0 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7 // indirect
|
||||
go.uber.org/mock v0.5.0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
|
@ -68,4 +82,5 @@ require (
|
|||
gorm.io/datatypes v1.2.5 // indirect
|
||||
gorm.io/driver/mysql v1.5.7 // indirect
|
||||
gorm.io/hints v1.1.2 // indirect
|
||||
lukechampine.com/blake3 v1.1.6 // indirect
|
||||
)
|
||||
|
|
39
go.sum
39
go.sum
|
@ -4,6 +4,8 @@ git.mstar.dev/mstar/goutils v1.14.2 h1:2W9AtsAAGR9OeztPnyVCkxiuZDe7h1DlXzil35wU+
|
|||
git.mstar.dev/mstar/goutils v1.14.2/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/PeerDB-io/gluabit32 v1.0.2 h1:AGI1Z7dwDVotakpuOOuyTX4/QGi5HUYsipL/VfodmO4=
|
||||
github.com/PeerDB-io/gluabit32 v1.0.2/go.mod h1:tsHStN1XG5uGVWEA8d/RameB7el3PE3sVkvk8e3+FJg=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||
|
@ -13,7 +15,11 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
|
|||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9 h1:rdWOzitWlNYeUsXmz+IQfa9NkGEq3gA/qQ3mOEqBU6o=
|
||||
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9/go.mod h1:X97UjDTXp+7bayQSFZk2hPvCTmTZIicUjZQRtkwgAKY=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cosmotek/loguago v1.0.0 h1:cM6xoMPoIL1hRPicMenFNVohylundRIPz+OfpadJyY0=
|
||||
github.com/cosmotek/loguago v1.0.0/go.mod h1:M/3wRiTLODLY6ufA9sVxOgSvnkYv53sYuDTQEqX0lZ4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
|
@ -28,6 +34,8 @@ github.com/go-acme/lego/v4 v4.23.1 h1:lZ5fGtGESA2L9FB8dNTvrQUq3/X4QOb8ExkKyY7LSV
|
|||
github.com/go-acme/lego/v4 v4.23.1/go.mod h1:7UMVR7oQbIYw6V7mTgGwi4Er7B6Ww0c+c8feiBM0EgI=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=
|
||||
github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
|
@ -46,6 +54,8 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0kt
|
|||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-tpm v0.9.3 h1:+yx0/anQuGzi+ssRqeD6WpXjW2L/V0dItUayO0i9sRc=
|
||||
|
@ -67,6 +77,13 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
|||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/kohkimakimoto/gluatemplate v0.0.0-20160815033744-d9e2c9d6b00f h1:CXJzfe/zhkWjXLAZItKA4BPHo4d8Fh7Hc4gqcLVyrWQ=
|
||||
github.com/kohkimakimoto/gluatemplate v0.0.0-20160815033744-d9e2c9d6b00f/go.mod h1:mepZlGlueX0FYzgC3KQMEuBBQuaAvdp8RUY+ZEe2fbI=
|
||||
github.com/layeh/gopher-json v0.0.0-20201124131017-552bb3c4c3bf h1:bg6J/5S/AeTz7K9i/luJRj31BJ8f+LgYwKQBSOZxSEM=
|
||||
github.com/layeh/gopher-json v0.0.0-20201124131017-552bb3c4c3bf/go.mod h1:E/q28EyUVBgBQnONAVPIdwvEsv4Ve0vaCA9JWim4+3I=
|
||||
github.com/lestrrat-go/blackmagic v1.0.3 h1:94HXkVLxkZO9vJI/w2u1T0DAoprShFd13xtnSINtDWs=
|
||||
github.com/lestrrat-go/blackmagic v1.0.3/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw=
|
||||
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
|
||||
|
@ -93,12 +110,22 @@ github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP
|
|||
github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
|
||||
github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ=
|
||||
github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
|
||||
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
|
||||
github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY=
|
||||
github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
github.com/nrednav/cuid2 v1.0.1 h1:aYLDCmGxEij7xCdiV6GVSPSlqFOS6sqHKKvBeKjddVY=
|
||||
github.com/nrednav/cuid2 v1.0.1/go.mod h1:nH9lUYqbtoVsnpy20etw5q1guTjE99Xy4EpmnK5nKm0=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
||||
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
|
@ -117,6 +144,8 @@ github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
|||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
|
@ -128,7 +157,13 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
|||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/yaronf/httpsign v0.3.2 h1:rBYYx9eHm60noI4oC24JAD2tJuM8AUDh9ErJO/FfzBs=
|
||||
github.com/yaronf/httpsign v0.3.2/go.mod h1:cYB/6toJrJnf4JTLVoo6IHzFH9/Zu1dcKmah4xfX2WA=
|
||||
github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7 h1:noHsffKZsNfU38DwcXWEPldrTjIZ8FPNKx8mYMGnqjs=
|
||||
github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7/go.mod h1:bbMEM6aU1WDF1ErA5YJ0p91652pGv140gGw4Ww3RGp8=
|
||||
github.com/yuin/gluare v0.0.0-20170607022532-d7c94f1a80ed h1:I1vcLHWU9m30rA90rMrKPu0eD3NDA4FBlkB8WMaDyUw=
|
||||
github.com/yuin/gluare v0.0.0-20170607022532-d7c94f1a80ed/go.mod h1:9w6KSdZh23UWqOywWsRLUcJUrUNjRh4Ql3z9uVgnSP4=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
|
||||
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
|
@ -179,6 +214,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
|
@ -206,3 +243,5 @@ gorm.io/hints v1.1.2 h1:b5j0kwk5p4+3BtDtYqqfY+ATSxjj+6ptPgVveuynn9o=
|
|||
gorm.io/hints v1.1.2/go.mod h1:/ARdpUHAtyEMCh5NNi3tI7FsGh+Cj/MIUlvNxCNCFWg=
|
||||
gorm.io/plugin/dbresolver v1.5.3 h1:wFwINGZZmttuu9h7XpvbDHd8Lf9bb8GNzp/NpAMV2wU=
|
||||
gorm.io/plugin/dbresolver v1.5.3/go.mod h1:TSrVhaUg2DZAWP3PrHlDlITEJmNOkL0tFTjvTEsQ4XE=
|
||||
lukechampine.com/blake3 v1.1.6 h1:H3cROdztr7RCfoaTpGZFQsrqvweFLrqS73j7L7cmR5c=
|
||||
lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
||||
|
|
12
plugins/api.go
Normal file
12
plugins/api.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package plugins
|
||||
|
||||
import lua "github.com/yuin/gopher-lua"
|
||||
|
||||
// TODO: Decide on the API made available to plugins
|
||||
// Everything has to be a function, assume no internal state
|
||||
// since the used lua state may vary between calls
|
||||
type linstromApi struct{}
|
||||
|
||||
func insertLinstromApiIntoState(l *lua.LState) error {
|
||||
panic("not implemented")
|
||||
}
|
62
plugins/init.go
Normal file
62
plugins/init.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.mstar.dev/mstar/goutils/other"
|
||||
"github.com/PeerDB-io/gluabit32"
|
||||
"github.com/cjoudrey/gluahttp"
|
||||
"github.com/cosmotek/loguago"
|
||||
"github.com/kohkimakimoto/gluatemplate"
|
||||
gluajson "github.com/layeh/gopher-json"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/yuin/gluare"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
|
||||
webshared "git.mstar.dev/mstar/linstrom/web/shared"
|
||||
)
|
||||
|
||||
// "github.com/CuberL/glua-async" // For async support, see module readme for how to
|
||||
// Use "github.com/layeh/gopher-luar" for implementing interface
|
||||
|
||||
// Create a new "blank" lua state for future use.
|
||||
// Each created state has to be properly closed.
|
||||
// A "blank" state has the base libraries preloaded and is technically ready to use.
|
||||
// Plugin specific functions and data is not yet included
|
||||
func NewBlankState() (*lua.LState, error) {
|
||||
l := lua.NewState()
|
||||
for _, pair := range []struct {
|
||||
n string
|
||||
f lua.LGFunction
|
||||
}{
|
||||
{lua.LoadLibName, lua.OpenPackage}, // Must always be first
|
||||
{lua.BaseLibName, lua.OpenBase},
|
||||
{lua.TabLibName, lua.OpenTable},
|
||||
// {lua.IoLibName, lua.OpenIo},
|
||||
{lua.OsLibName, lua.OpenOs},
|
||||
{lua.StringLibName, lua.OpenString},
|
||||
{lua.MathLibName, lua.OpenMath},
|
||||
// {lua.DebugLibName, lua.OpenDebug},
|
||||
{lua.ChannelLibName, lua.OpenChannel},
|
||||
{lua.CoroutineLibName, lua.OpenCoroutine},
|
||||
{"bit32", gluabit32.Loader},
|
||||
{"json", gluajson.Loader},
|
||||
{"log", loguago.NewLogger(log.Logger).Loader}, // TODO: Decide if used logger should be passed in via context
|
||||
{"http", gluahttp.NewHttpModule(&webshared.RequestClient).Loader}, // TODO: Modify this to support signing
|
||||
{"re", gluare.Loader},
|
||||
{"texttemplate", gluatemplate.Loader}, // TODO: Copy this lib, but modify to use html/template instead
|
||||
} {
|
||||
if err := l.CallByParam(lua.P{
|
||||
Fn: l.NewFunction(pair.f),
|
||||
NRet: 0,
|
||||
Protect: true,
|
||||
}, lua.LString(pair.n)); err != nil {
|
||||
return nil, other.Error(
|
||||
"plugins",
|
||||
fmt.Sprintf("Failed to preload lua library %q into state", pair.n),
|
||||
err,
|
||||
)
|
||||
}
|
||||
}
|
||||
return l, nil
|
||||
}
|
67
plugins/pluginHolder.go
Normal file
67
plugins/pluginHolder.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package plugins
|
||||
|
||||
import lua "github.com/yuin/gopher-lua"
|
||||
|
||||
/*
|
||||
Plugin hooks:
|
||||
- Pre local message
|
||||
- Post local message
|
||||
- Pre external message (received but not processed by default stuff)
|
||||
- Post external message (received, internal processing done)
|
||||
- Post new local account
|
||||
- Pre new remote account discovered
|
||||
- Post new remote account discovered
|
||||
*/
|
||||
|
||||
type pluginHolder struct {
|
||||
meta *PluginMetadata
|
||||
table *lua.LTable
|
||||
|
||||
// ---- Section hooks
|
||||
|
||||
postLocalMessage *lua.LFunction
|
||||
postExternalMessage *lua.LFunction
|
||||
postNewLocalAccount *lua.LFunction
|
||||
postRemoteAccountDiscovered *lua.LFunction
|
||||
// preLocalMessage *lua.LFunction
|
||||
// preExternalMessage *lua.LFunction // Might not want this
|
||||
// preRemoteAccountDiscovered *lua.LFunction
|
||||
}
|
||||
|
||||
type PluginMetadata struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
// Don't load major and minor versions from meta file, calc from full version instead
|
||||
Major int `json:"-"`
|
||||
Minor int `json:"-"`
|
||||
Source string `json:"source"`
|
||||
License string `json:"license"`
|
||||
Hashes map[string]string `json:"hashes"`
|
||||
EntryFile string `json:"entry"`
|
||||
HookNames map[string]string `json:"hook_names"`
|
||||
}
|
||||
|
||||
const (
|
||||
HookPostLocalMessage = "post-local-message"
|
||||
HookPostExternalMessage = "post-external-message"
|
||||
HookPostNewLocalAccount = "post-new-local-account"
|
||||
HookPostRemoteAccountDiscovered = "post-remote-account-discovered"
|
||||
)
|
||||
|
||||
// TODO: Figure out signature
|
||||
func (p *pluginHolder) PostLocalMessage(l *lua.LState) error {
|
||||
// Only act on the hook if a hook exists
|
||||
if p.postLocalMessage != nil {
|
||||
err := l.CallByParam(lua.P{
|
||||
Fn: p.postLocalMessage,
|
||||
NRet: 1, // TODO: Adjust based on signature
|
||||
Protect: true,
|
||||
}) // TODO: Translate signature arguments into LValues and include here
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Translate args on stack back into whats expected from the signature
|
||||
panic("not implemented")
|
||||
}
|
||||
return nil
|
||||
}
|
200
plugins/pluginLoader.go
Normal file
200
plugins/pluginLoader.go
Normal file
|
@ -0,0 +1,200 @@
|
|||
package plugins
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
"git.mstar.dev/mstar/goutils/other"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
"github.com/yuin/gopher-lua/parse"
|
||||
)
|
||||
|
||||
/*
|
||||
Plugin structure expectation:
|
||||
- meta.json for plugin metadata:
|
||||
- version
|
||||
- name
|
||||
- source location (where the plugin can be sourced from)
|
||||
- license
|
||||
- file hashes (every file in the plugin dir, sha256, hex encoded)
|
||||
- entry file name
|
||||
- Hook to table key name list (which function in the returned table is for what hook)
|
||||
- Entry script returns a table
|
||||
*/
|
||||
|
||||
const PluginMetadataFileName = "meta.json"
|
||||
|
||||
var (
|
||||
ErrNoHashForFile = errors.New("no hash for file in the metadata")
|
||||
ErrInvalidHash = errors.New("hashes don't match")
|
||||
ErrMissingFile = errors.New("a required file is missing")
|
||||
ErrInvalidEntryReturnValue = errors.New(
|
||||
"entry script returned an invalid value. Must be a table",
|
||||
)
|
||||
)
|
||||
|
||||
var compCache = map[string]*lua.FunctionProto{}
|
||||
var compCacheLock = sync.RWMutex{}
|
||||
|
||||
// Load the plugin located in a provided folder into the given state.
|
||||
// Validates the data, compiles it for future reuse and links up the hooks
|
||||
func LoadPlugin(location string, lState *lua.LState) (*pluginHolder, error) {
|
||||
metaFileData, err := os.ReadFile(location + "/" + PluginMetadataFileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
metadata := PluginMetadata{}
|
||||
err = json.Unmarshal(metaFileData, &metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compCacheLock.RLock()
|
||||
precompiled, ok := compCache[metadata.Name+metadata.Version]
|
||||
compCacheLock.RUnlock()
|
||||
if !ok {
|
||||
// This version of a plugin not in the cache yet, validate the plugin dir, compile it and add it to the cache
|
||||
precompiled, err = compilePluginDir(&metadata, location)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compCacheLock.Lock()
|
||||
compCache[metadata.Name+metadata.Version] = precompiled
|
||||
compCacheLock.Unlock()
|
||||
}
|
||||
lFunc := lState.NewFunctionFromProto(precompiled)
|
||||
lState.Push(lFunc)
|
||||
if err = lState.PCall(0, lua.MultRet, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return generatePluginHolder(lState, &metadata)
|
||||
}
|
||||
|
||||
// Compiles a given lua file for future use
|
||||
func compileFile(filePath string) (*lua.FunctionProto, error) {
|
||||
file, err := os.Open(filePath)
|
||||
defer func() { _ = file.Close() }()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reader := bufio.NewReader(file)
|
||||
chunk, err := parse.Parse(reader, filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
proto, err := lua.Compile(chunk, filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return proto, nil
|
||||
}
|
||||
|
||||
// Validates the given plugin dir and compiles it for future use
|
||||
func compilePluginDir(metadata *PluginMetadata, location string) (*lua.FunctionProto, error) {
|
||||
if err := checkDir(location, "", metadata.Hashes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entryFileName := path.Join(location, metadata.EntryFile)
|
||||
if _, err := os.Stat(entryFileName); err != nil {
|
||||
return nil, other.Error("plugins", fmt.Sprintf("missing entry file %s", entryFileName), err)
|
||||
}
|
||||
compiled, err := compileFile(entryFileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return compiled, nil
|
||||
}
|
||||
|
||||
// Ensures that all files in the given root directory (plus suffix) match the expected hashes provided in the metadata
|
||||
func checkDir(rootPath string, suffix string, expectedHashes map[string]string) error {
|
||||
rootEntries, err := os.ReadDir(path.Join(rootPath, suffix))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, entry := range rootEntries {
|
||||
if suffix == "" && entry.Name() == PluginMetadataFileName {
|
||||
continue
|
||||
}
|
||||
if entry.IsDir() {
|
||||
if err = checkDir(rootPath, path.Join(suffix, entry.Name()), expectedHashes); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fileName := path.Join(rootPath, suffix, entry.Name())
|
||||
expectedHash, ok := expectedHashes[fileName]
|
||||
if !ok {
|
||||
return other.Error(
|
||||
"plugins",
|
||||
fmt.Sprintf("No hash found in metadata for file %s", fileName),
|
||||
ErrNoHashForFile,
|
||||
)
|
||||
}
|
||||
f, err := os.Open(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
if err = checkHash(f, expectedHash); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Checks if a hash matches the given file
|
||||
func checkHash(file *os.File, expected string) error {
|
||||
hasher := sha256.New()
|
||||
_, err := io.Copy(hasher, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sum := hasher.Sum([]byte{})
|
||||
if expected != hex.EncodeToString(sum) {
|
||||
return ErrInvalidHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Properly inserts the plugin into the state's global context.
|
||||
// Also gets links to all functions found that are named as hook in the metadata.
|
||||
// Assumptions: Called after the entry file has been run, but before any other operations
|
||||
func generatePluginHolder(l *lua.LState, meta *PluginMetadata) (*pluginHolder, error) {
|
||||
pluginTable, ok := l.Get(1).(*lua.LTable)
|
||||
if !ok || pluginTable.MaxN() != 0 {
|
||||
return nil, ErrInvalidEntryReturnValue
|
||||
}
|
||||
l.SetGlobal(meta.Name, pluginTable)
|
||||
pMap := lTableToMap(pluginTable)
|
||||
holder := pluginHolder{
|
||||
meta: meta,
|
||||
table: pluginTable,
|
||||
}
|
||||
if postLocalMessageHookName, ok := meta.HookNames[HookPostLocalMessage]; ok {
|
||||
if lV, ok := pMap[lua.LString(postLocalMessageHookName)].(*lua.LFunction); ok {
|
||||
holder.postLocalMessage = lV
|
||||
}
|
||||
}
|
||||
if postExternalMessageHookName, ok := meta.HookNames[HookPostExternalMessage]; ok {
|
||||
if lV, ok := pMap[lua.LString(postExternalMessageHookName)].(*lua.LFunction); ok {
|
||||
holder.postExternalMessage = lV
|
||||
}
|
||||
}
|
||||
if postNewLocalAccountName, ok := meta.HookNames[HookPostNewLocalAccount]; ok {
|
||||
if lV, ok := pMap[lua.LString(postNewLocalAccountName)].(*lua.LFunction); ok {
|
||||
holder.postNewLocalAccount = lV
|
||||
}
|
||||
}
|
||||
if postRemoteAccountDiscoveredName, ok := meta.HookNames[HookPostRemoteAccountDiscovered]; ok {
|
||||
if lV, ok := pMap[lua.LString(postRemoteAccountDiscoveredName)].(*lua.LFunction); ok {
|
||||
holder.postRemoteAccountDiscovered = lV
|
||||
}
|
||||
}
|
||||
return &holder, nil
|
||||
}
|
23
plugins/runner.go
Normal file
23
plugins/runner.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package plugins
|
||||
|
||||
import lua "github.com/yuin/gopher-lua"
|
||||
|
||||
type Runner struct {
|
||||
state *lua.LState
|
||||
inUse bool
|
||||
}
|
||||
|
||||
func NewRunner() (*Runner, error) {
|
||||
lState, err := NewBlankState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Runner{
|
||||
lState,
|
||||
false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Runner) IsInUse() bool {
|
||||
return r.inUse
|
||||
}
|
11
plugins/util.go
Normal file
11
plugins/util.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package plugins
|
||||
|
||||
import lua "github.com/yuin/gopher-lua"
|
||||
|
||||
func lTableToMap(t *lua.LTable) map[lua.LValue]lua.LValue {
|
||||
m := map[lua.LValue]lua.LValue{}
|
||||
t.ForEach(func(l1, l2 lua.LValue) {
|
||||
m[l1] = l2
|
||||
})
|
||||
return m
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue