diff --git a/cmd/dfs-cli/cmd/filesystem.go b/cmd/dfs-cli/cmd/filesystem.go index ed534786..e4f69132 100644 --- a/cmd/dfs-cli/cmd/filesystem.go +++ b/cmd/dfs-cli/cmd/filesystem.go @@ -122,10 +122,6 @@ func statFileOrDirectory(podName, statElement string) { fmt.Println("Cr. Time : ", time.Unix(crTime, 0).String()) fmt.Println("Mo. Time : ", time.Unix(accTime, 0).String()) fmt.Println("Ac. Time : ", time.Unix(modTime, 0).String()) - for _, b := range resp.Blocks { - blkStr := fmt.Sprintf("0x%s, %s bytes, %s bytes", b.Reference, b.Size, b.CompressedSize) - fmt.Println(blkStr) - } } else { fmt.Println("stat: ", err) return diff --git a/cmd/dfs/cmd/server.go b/cmd/dfs/cmd/server.go index 55b30a6d..40a1d8e0 100644 --- a/cmd/dfs/cmd/server.go +++ b/cmd/dfs/cmd/server.go @@ -117,7 +117,8 @@ can consume it.`, return fmt.Errorf("postageBlockId is invalid") } } - ensConfig := &contracts.Config{} + ensConfig := &contracts.ENSConfig{} + var subscriptionConfig *contracts.SubscriptionConfig network := config.GetString("network") rpc := config.GetString(optionRPC) if rpc == "" { @@ -152,7 +153,7 @@ can consume it.`, return fmt.Errorf("ensRegistry contract address is missing") } - ensConfig = &contracts.Config{ + ensConfig = &contracts.ENSConfig{ ENSRegistryAddress: ensRegistryAddress, FDSRegistrarAddress: fdsRegistrarAddress, PublicResolverAddress: publicResolverAddress, @@ -164,12 +165,15 @@ can consume it.`, fmt.Println("\nens is not available for mainnet yet") return fmt.Errorf("ens is not available for mainnet yet") case "testnet": - ensConfig = contracts.TestnetConfig() + ensConfig, subscriptionConfig = contracts.TestnetConfig() case "play": - ensConfig = contracts.PlayConfig() + ensConfig, subscriptionConfig = contracts.PlayConfig() } } ensConfig.ProviderBackend = rpc + if subscriptionConfig != nil { + subscriptionConfig.RPC = rpc + } var logger logging.Logger switch v := strings.ToLower(verbosity); v { case "0", "silent": @@ -202,8 +206,8 @@ can consume it.`, ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() - // datadir will be removed in some future version. it is kept for migration purpose only - hdlr, err := api.New(ctx, beeApi, cookieDomain, postageBlockId, corsOrigins, ensConfig, logger) + + hdlr, err := api.New(ctx, beeApi, cookieDomain, postageBlockId, corsOrigins, ensConfig, nil, logger) if err != nil { logger.Error(err.Error()) return err @@ -271,6 +275,15 @@ func startHttpService(logger logging.Logger) *http.Server { httpSwagger.URL("./swagger/doc.json"), )).Methods(http.MethodGet) } + router.HandleFunc("/public-file", handler.PublicPodGetFileHandler) + router.HandleFunc("/public-dir", handler.PublicPodGetDirHandler) + router.HandleFunc("/public-kv", handler.PublicPodKVEntryGetHandler) + + redirectHandler := func(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, r.URL.Path+"/", http.StatusMovedPermanently) + } + router.HandleFunc("/public/{ref}", redirectHandler) + router.HandleFunc("/public/{ref}/{file:.*}", handler.PublicPodFilePathHandler) apiVersion := "v1" diff --git a/cmd/dfs/cmd/server_test.go b/cmd/dfs/cmd/server_test.go index a6b481f7..9437008c 100644 --- a/cmd/dfs/cmd/server_test.go +++ b/cmd/dfs/cmd/server_test.go @@ -576,7 +576,7 @@ func TestApis(t *testing.T) { t.Fatal(err) } if renameResp.StatusCode != 200 { - t.Fatal("rename failed", u) + t.Fatal("rename failed", u, renameResp.StatusCode) } } diff --git a/go.mod b/go.mod index 08f2d8e2..6a74c092 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/btcsuite/btcd v0.22.3 github.com/c-bata/go-prompt v0.2.6 github.com/dustin/go-humanize v1.0.1 - github.com/ethereum/go-ethereum v1.11.1 + github.com/ethereum/go-ethereum v1.11.4 github.com/ethersphere/bee v1.12.0 github.com/ethersphere/bmt v0.1.4 github.com/fairdatasociety/fairOS-dfs-utils v0.0.0-20221230123929-aec4ed8b854d @@ -15,7 +15,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/gorilla/securecookie v1.1.1 github.com/gorilla/websocket v1.5.0 - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d + github.com/hashicorp/golang-lru v0.6.0 github.com/klauspost/pgzip v1.2.5 github.com/miguelmota/go-ethereum-hdwallet v0.1.1 github.com/mitchellh/go-homedir v1.1.0 @@ -24,15 +24,15 @@ require ( github.com/sirupsen/logrus v1.9.0 github.com/spf13/cobra v1.6.1 github.com/spf13/viper v1.15.0 - github.com/stretchr/testify v1.8.1 - github.com/swaggo/http-swagger v1.3.3 + github.com/stretchr/testify v1.8.2 + github.com/swaggo/http-swagger v1.3.4 github.com/swaggo/swag v1.8.10 github.com/tinygrasshopper/bettercsv v0.0.1 github.com/tyler-smith/go-bip39 v1.1.0 github.com/wealdtech/go-ens/v3 v3.5.5 - go.uber.org/goleak v1.2.0 - golang.org/x/crypto v0.1.0 - golang.org/x/term v0.5.0 + go.uber.org/goleak v1.2.1 + golang.org/x/crypto v0.4.0 + golang.org/x/term v0.6.0 gopkg.in/yaml.v2 v2.4.0 resenje.org/jsonhttp v0.2.0 ) @@ -44,7 +44,7 @@ require ( github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect @@ -55,10 +55,10 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect - github.com/ipfs/go-cid v0.2.0 // indirect + github.com/ipfs/go-cid v0.3.2 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect - github.com/klauspost/cpuid/v2 v2.0.11 // indirect + github.com/klauspost/cpuid/v2 v2.2.1 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -68,11 +68,11 @@ require ( github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect - github.com/multiformats/go-base32 v0.0.4 // indirect - github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect github.com/multiformats/go-multibase v0.1.1 // indirect - github.com/multiformats/go-multihash v0.2.0 // indirect - github.com/multiformats/go-varint v0.0.6 // indirect + github.com/multiformats/go-multihash v0.2.1 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pkg/term v1.2.0-beta.2 // indirect @@ -90,11 +90,11 @@ require ( github.com/tklauser/numcpus v0.4.0 // indirect github.com/wealdtech/go-multicodec v1.4.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect - go.uber.org/atomic v1.9.0 // indirect - golang.org/x/net v0.4.0 // indirect - golang.org/x/sys v0.5.0 // indirect + go.uber.org/atomic v1.10.0 // indirect + golang.org/x/net v0.7.0 // indirect + golang.org/x/sys v0.6.0 // indirect golang.org/x/text v0.7.0 // indirect - golang.org/x/tools v0.2.0 // indirect + golang.org/x/tools v0.3.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 340181ad..c79ca2f8 100644 --- a/go.sum +++ b/go.sum @@ -142,9 +142,8 @@ github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vs github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= @@ -164,8 +163,8 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= -github.com/ethereum/go-ethereum v1.11.1 h1:EMymmWFzpS7G9l9NvVN8G73cgdUIqDPNRf2YTSGBXlk= -github.com/ethereum/go-ethereum v1.11.1/go.mod h1:DuefStAgaxoaYGLR0FueVcVbehmn5n9QUcVrMCuOvuc= +github.com/ethereum/go-ethereum v1.11.4 h1:KG81SnUHXWk8LJB3mBcHg/E2yLvXoiPmRMCIRxgx3cE= +github.com/ethereum/go-ethereum v1.11.4/go.mod h1:it7x0DWnTDMfVFdXcU6Ti4KEFQynLHVRarcSlPr0HBo= github.com/ethersphere/bee v1.12.0 h1:dKtaKQXYFSnjB/8g0qlhIc1BVVvKJ1DCTL5NuOtz2mI= github.com/ethersphere/bee v1.12.0/go.mod h1:rm4lICvmvSMQ4EnrPYxZsWFkzMh66XqNOKpj1HSJnA4= github.com/ethersphere/bmt v0.1.4 h1:+rkWYNtMgDx6bkNqGdWu+U9DgGI1rRZplpSW3YhBr1Q= @@ -211,6 +210,7 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -298,11 +298,11 @@ github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1 github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= +github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= @@ -324,8 +324,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/ipfs/go-cid v0.2.0 h1:01JTiihFq9en9Vz0lc0VDWvZe/uBonGpzo4THP0vcQ0= -github.com/ipfs/go-cid v0.2.0/go.mod h1:P+HXFDF4CVhaVayiEb4wkAy7zBHxBwsJyt0Y5U6MLro= +github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc= +github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= @@ -354,8 +354,8 @@ github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9 github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.11 h1:i2lw1Pm7Yi/4O6XCSyJWqEHI2MDw2FzUK6o/D21xn2A= -github.com/klauspost/cpuid/v2 v2.0.11/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.2.1 h1:U33DW0aiEj633gHYw3LoDNfkDiYnE5Q8M/TKJn2f2jI= +github.com/klauspost/cpuid/v2 v2.2.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= @@ -369,6 +369,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -419,16 +420,16 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb 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/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= -github.com/multiformats/go-base32 v0.0.4 h1:+qMh4a2f37b4xTNs6mqitDinryCI+tfO2dRVMN9mjSE= -github.com/multiformats/go-base32 v0.0.4/go.mod h1:jNLFzjPZtp3aIARHbJRZIaPuspdH0J6q39uUM5pnABM= -github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= -github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI= github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8= -github.com/multiformats/go-multihash v0.2.0 h1:oytJb9ZA1OUW0r0f9ea18GiaPOo4SXyc7p2movyUuo4= -github.com/multiformats/go-multihash v0.2.0/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= -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/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= +github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= @@ -481,7 +482,6 @@ github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8u github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= @@ -540,14 +540,15 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a h1:kAe4YSu0O0UFn1DowNo2MY5p6xzqtJ/wQ7LZynSvGaY= github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= -github.com/swaggo/http-swagger v1.3.3 h1:Hu5Z0L9ssyBLofaama21iYaF2VbWyA8jdohaaCGpHsc= -github.com/swaggo/http-swagger v1.3.3/go.mod h1:sE+4PjD89IxMPm77FnkDz0sdO+p5lbXzrVWT6OTVVGo= +github.com/swaggo/http-swagger v1.3.4 h1:q7t/XLx0n15H1Q9/tk3Y9L4n210XzJF5WtnDX64a5ww= +github.com/swaggo/http-swagger v1.3.4/go.mod h1:9dAh0unqMBAlbp1uE2Uc2mQTxNMU/ha4UbucIg1MFkQ= github.com/swaggo/swag v1.8.10 h1:eExW4bFa52WOjqRzRD58bgWsWfdFJso50lpbeTcmTfo= github.com/swaggo/swag v1.8.10/go.mod h1:ezQVUUhly8dludpVk+/PuwJWvLLanB13ygV5Pr9enSk= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= @@ -590,10 +591,11 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -610,8 +612,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8= +golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -639,7 +641,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -652,7 +653,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= +golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -693,8 +694,8 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -772,14 +773,15 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -846,8 +848,8 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/gomobile/README.md b/gomobile/README.md index ba9affe2..54f551ea 100644 --- a/gomobile/README.md +++ b/gomobile/README.md @@ -1,3 +1,5 @@ +[![Go Reference](https://pkg.go.dev/badge/github.com/fairdatasociety/fairOS-dfs@master/gomobile.svg)](https://pkg.go.dev/github.com/fairdatasociety/fairOS-dfs@master/gomobile) + # gomobile client for fairOS-dfs Now fairOS-dfs can be used as android or @@ -22,7 +24,66 @@ Coming soon ``` ### How to use in android? -Check out this [demo](https://github.com/fairDataSociety/fairOS-dfs-android-demo) + +#### API +``` + + // isConnected checks if dfs.API is already initialised + public static native boolean isConnected(); + + // connect with a bee and initialise dfs.API + public static native void connect(String beeEndpoint, String postageBlockId, String network, String rpc, long logLevel) throws Exception; + + public static native String loginUser(String username, String password) throws Exception; + public static native boolean isUserPresent(String username); + public static native boolean isUserLoggedIn(); + public static native void logoutUser() throws Exception; + public static native String statUser() throws Exception; + + public static native String newPod(String podName) throws Exception; + public static native String podOpen(String podName) throws Exception; + public static native void podClose(String podName) throws Exception; + public static native void podDelete(String podName) throws Exception; + public static native void podSync(String podName) throws Exception; + public static native String podList() throws Exception; + public static native String podStat(String podName) throws Exception; + public static native boolean isPodPresent(String podName); + public static native String podShare(String podName) throws Exception; + public static native String podReceive(String podSharingReference) throws Exception; + public static native String podReceiveInfo(String podSharingReference) throws Exception; + + public static native String dirPresent(String podName, String dirPath) throws Exception; + public static native String dirMake(String podName, String dirPath) throws Exception; + public static native String dirRemove(String podName, String dirPath) throws Exception; + public static native String dirList(String podName, String dirPath) throws Exception; + public static native String dirStat(String podName, String dirPath) throws Exception; + + public static native String fileShare(String podName, String dirPath, String destinationUser) throws Exception; + public static native String fileReceive(String podName, String directory, String fileSharingReference) throws Exception; + public static native String fileReceiveInfo(String podName, String fileSharingReference) throws Exception; + public static native void fileDelete(String podName, String filePath) throws Exception; + public static native String fileStat(String podName, String filePath) throws Exception; + public static native void fileUpload(String podName, String filePath, String dirPath, String compression, String blockSize, boolean overwrite) throws Exception; + public static native void blobUpload(byte[] data, String podName, String filePath, String dirPath, String compression, long size, long blockSize, boolean overwrite) throws Exception; + public static native byte[] fileDownload(String podName, String filePath) throws Exception; + + public static native String version(); + +``` +***Document store and KV store documentation coming soon*** + +#### API flow + +To use the fairOS-dfs in your android app you have to download the `fairos.aar` file from the downloads section + +Before calling any of the functions we need to connect with the swarm through a bee node and initialise fairos dfs API. +For that we call `connect` function with the necessary parameters. + +We follow the normal flow of tasks after that, such as login, list user pods, opening a pod and list files and directories, upload or download content. + +The function names are pretty much self-explanatory. + +Check out this working [demo](https://github.com/fairDataSociety/fairOS-dfs-android-demo). *** The code is not fully tested. Please use [fairOS-dfs](https://github.com/fairDataSociety/fairOS-dfs) for a better experience. diff --git a/gomobile/dfs.go b/gomobile/dfs.go index 37ff1866..f0d4abfd 100644 --- a/gomobile/dfs.go +++ b/gomobile/dfs.go @@ -45,12 +45,12 @@ func IsConnected() bool { func Connect(beeEndpoint, postageBlockId, network, rpc string, logLevel int) error { logger := logging.New(os.Stdout, logrus.Level(logLevel)) var err error - var ensConfig *contracts.Config + var ensConfig *contracts.ENSConfig switch network { case "play": - ensConfig = contracts.PlayConfig() + ensConfig, _ = contracts.PlayConfig() case "testnet": - ensConfig = contracts.TestnetConfig() + ensConfig, _ = contracts.TestnetConfig() case "mainnet": return fmt.Errorf("not supported yet") default: @@ -61,6 +61,7 @@ func Connect(beeEndpoint, postageBlockId, network, rpc string, logLevel int) err beeEndpoint, postageBlockId, ensConfig, + nil, logger, ) return err @@ -93,10 +94,6 @@ func LogoutUser() error { return api.LogoutUser(sessionId) } -func DeleteUser() error { - return api.DeleteUserV2(savedPassword, sessionId) -} - func StatUser() (string, error) { stat, err := api.GetUserStat(sessionId) if err != nil { @@ -213,7 +210,7 @@ func DirPresent(podName, dirPath string) (string, error) { } func DirMake(podName, dirPath string) (string, error) { - err := api.Mkdir(podName, dirPath, sessionId) + err := api.Mkdir(podName, dirPath, sessionId, 0) if err != nil { return "", err } @@ -269,11 +266,7 @@ func FileShare(podName, dirPath, destinationUser string) (string, error) { } func FileReceive(podName, directory, fileSharingReference string) (string, error) { - ref, err := utils.ParseSharingReference(fileSharingReference) - if err != nil { - return "", err - } - filePath, err := api.ReceiveFile(podName, sessionId, ref, directory) + filePath, err := api.ReceiveFile(podName, sessionId, fileSharingReference, directory) if err != nil { return "", err } @@ -284,11 +277,7 @@ func FileReceive(podName, directory, fileSharingReference string) (string, error } func FileReceiveInfo(podName, fileSharingReference string) (string, error) { - ref, err := utils.ParseSharingReference(fileSharingReference) - if err != nil { - return "", err - } - receiveInfo, err := api.ReceiveInfo(sessionId, ref) + receiveInfo, err := api.ReceiveInfo(sessionId, fileSharingReference) if err != nil { return "", err } @@ -323,12 +312,12 @@ func FileUpload(podName, filePath, dirPath, compression, blockSize string, overw if err != nil { return err } - return api.UploadFile(podName, fileInfo.Name(), sessionId, fileInfo.Size(), f, dirPath, compression, uint32(bs), overwrite) + return api.UploadFile(podName, fileInfo.Name(), sessionId, fileInfo.Size(), f, dirPath, compression, uint32(bs), 0, overwrite) } func BlobUpload(data []byte, podName, fileName, dirPath, compression string, size, blockSize int64, overwrite bool) error { r := bytes.NewReader(data) - return api.UploadFile(podName, fileName, sessionId, size, r, dirPath, compression, uint32(blockSize), overwrite) + return api.UploadFile(podName, fileName, sessionId, size, r, dirPath, compression, uint32(blockSize), 0, overwrite) } func FileDownload(podName, filePath string) ([]byte, error) { diff --git a/pkg/account/account.go b/pkg/account/account.go index 472ab499..24895c12 100644 --- a/pkg/account/account.go +++ b/pkg/account/account.go @@ -37,7 +37,8 @@ const ( UserAccountIndex = -1 // seedSize is used to determine how much padding we need for portable account SOC - seedSize = 64 + seedSize = 64 + usernameLengthSize = 1 ) // Account is used for keeping authenticated logged-in user info in the session @@ -272,3 +273,38 @@ func (*Info) RemovePadFromSeed(paddedSeed []byte, passphrase string) ([]byte, er return decryptedBytes[:seedSize], nil } + +// PadSeedName pads the given seed and name with random elements to be a chunk of chunkSize +func (*Info) PadSeedName(seed []byte, username string, passphrase string) ([]byte, error) { + usernameLength := len(username) + if usernameLength > 255 { + return nil, fmt.Errorf("username length is too long") + } + usernameLengthBytes := make([]byte, usernameLengthSize) + usernameLengthBytes[0] = byte(usernameLength) + paddingLength := utils.MaxChunkLength - aes.BlockSize - seedSize - usernameLengthSize - usernameLength + randomBytes, err := utils.GetRandBytes(paddingLength) + if err != nil { // skipcq: TCV-001 + return nil, err + } + chunkData := make([]byte, 0, utils.MaxChunkLength) + chunkData = append(chunkData, seed...) + chunkData = append(chunkData, usernameLengthBytes...) + chunkData = append(chunkData, []byte(username)...) + chunkData = append(chunkData, randomBytes...) + encryptedBytes, err := utils.EncryptBytes([]byte(passphrase), chunkData) + if err != nil { // skipcq: TCV-001 + return nil, fmt.Errorf("mnemonic padding failed: %w", err) + } + return encryptedBytes, nil +} + +// RemovePadFromSeedName removes the padding of random elements from the given data and returns the seed and name +func (*Info) RemovePadFromSeedName(paddedSeed []byte, passphrase string) ([]byte, string, error) { + decryptedBytes, err := utils.DecryptBytes([]byte(passphrase), paddedSeed) + if err != nil { // skipcq: TCV-001 + return nil, "", fmt.Errorf("seed decryption failed: %w", err) + } + usernameLength := int(decryptedBytes[seedSize]) + return decryptedBytes[:seedSize], string(decryptedBytes[seedSize+usernameLengthSize : seedSize+usernameLengthSize+usernameLength]), nil +} diff --git a/pkg/account/account_test.go b/pkg/account/account_test.go index 0685398c..018cf873 100644 --- a/pkg/account/account_test.go +++ b/pkg/account/account_test.go @@ -132,6 +132,40 @@ func TestPadUnpadSeed(t *testing.T) { } } +func TestPadUnpadSeedName(t *testing.T) { + name := "TestPadUnpadSeedName" + password := "letmein" + logger := logging.New(io.Discard, 0) + acc := New(logger) + _, seed, err := acc.CreateUserAccount("") + if err != nil { + t.Fatal(err) + } + + acc.wallet.seed = seed + r, err := acc.userAccount.PadSeedName(seed, name, password) + if err != nil { + t.Fatal(err) + } + + if len(r) != utils.MaxChunkLength { + t.Fatal("padded string does not match chunk size") + } + + seed2, name2, err := acc.userAccount.RemovePadFromSeedName(r, password) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(seed, seed2) { + t.Fatal("seed and padding removed seed do not match") + } + + if name != name2 { + t.Fatal("name do not match") + } +} + func TestCreatePodAccount(t *testing.T) { logger := logging.New(io.Discard, 0) acc := New(logger) diff --git a/pkg/api/dir_mkdir.go b/pkg/api/dir_mkdir.go index 8d3bb2e9..8d16549d 100644 --- a/pkg/api/dir_mkdir.go +++ b/pkg/api/dir_mkdir.go @@ -91,7 +91,7 @@ func (h *Handler) DirectoryMkdirHandler(w http.ResponseWriter, r *http.Request) } // make directory - err = h.dfsAPI.Mkdir(podName, dirToCreateWithPath, sessionId) + err = h.dfsAPI.Mkdir(podName, dirToCreateWithPath, sessionId, 0) if err != nil { if err == dfs.ErrPodNotOpen || err == dfs.ErrUserNotLoggedIn || err == p.ErrInvalidDirectory || diff --git a/pkg/api/file_download.go b/pkg/api/file_download.go index 3aad206a..3e72d884 100644 --- a/pkg/api/file_download.go +++ b/pkg/api/file_download.go @@ -125,7 +125,7 @@ func (h *Handler) handleDownload(w http.ResponseWriter, r *http.Request, podName jsonhttp.BadRequest(w, "download: "+err.Error()) return } - if err == file.ErrFileNotPresent || err == file.ErrFileNotFound { + if err == file.ErrFileNotFound { h.logger.Errorf("download: %v", err) jsonhttp.NotFound(w, "download: "+err.Error()) return diff --git a/pkg/api/file_share.go b/pkg/api/file_share.go index 25dd96eb..1ff18e76 100644 --- a/pkg/api/file_share.go +++ b/pkg/api/file_share.go @@ -23,7 +23,6 @@ import ( "resenje.org/jsonhttp" "github.com/fairdatasociety/fairOS-dfs/pkg/cookie" - "github.com/fairdatasociety/fairOS-dfs/pkg/utils" ) // ReceiveFileResponse represents the response for receiving a file @@ -182,14 +181,7 @@ func (h *Handler) FileReceiveHandler(w http.ResponseWriter, r *http.Request) { return } - sharingRef, err := utils.ParseSharingReference(sharingRefString) - if err != nil { - h.logger.Errorf("file receive: invalid reference: ", err) - jsonhttp.BadRequest(w, &response{Message: "file receive: invalid reference:" + err.Error()}) - return - } - - filePath, err := h.dfsAPI.ReceiveFile(podName, sessionId, sharingRef, dir) + filePath, err := h.dfsAPI.ReceiveFile(podName, sessionId, sharingRefString, dir) if err != nil { h.logger.Errorf("file receive: %v", err) jsonhttp.InternalServerError(w, &response{Message: "file receive: " + err.Error()}) @@ -242,14 +234,7 @@ func (h *Handler) FileReceiveInfoHandler(w http.ResponseWriter, r *http.Request) return } - sharingRef, err := utils.ParseSharingReference(sharingRefString) - if err != nil { - h.logger.Errorf("file receive info: invalid reference: ", err) - jsonhttp.BadRequest(w, &response{Message: "file receive info: invalid reference:" + err.Error()}) - return - } - - receiveInfo, err := h.dfsAPI.ReceiveInfo(sessionId, sharingRef) + receiveInfo, err := h.dfsAPI.ReceiveInfo(sessionId, sharingRefString) if err != nil { h.logger.Errorf("file receive info: %v", err) jsonhttp.InternalServerError(w, &response{Message: "file receive info: " + err.Error()}) diff --git a/pkg/api/file_status.go b/pkg/api/file_status.go index 1aee1424..0bc9642d 100644 --- a/pkg/api/file_status.go +++ b/pkg/api/file_status.go @@ -78,7 +78,7 @@ func (h *Handler) FileStatusHandler(w http.ResponseWriter, r *http.Request) { jsonhttp.BadRequest(w, "status: "+err.Error()) return } - if err == file.ErrFileNotPresent || err == file.ErrFileNotFound { + if err == file.ErrFileNotFound { h.logger.Errorf("status: %v", err) jsonhttp.NotFound(w, "status: "+err.Error()) return diff --git a/pkg/api/file_upload.go b/pkg/api/file_upload.go index 8e7f6543..bec0551a 100644 --- a/pkg/api/file_upload.go +++ b/pkg/api/file_upload.go @@ -170,5 +170,5 @@ func (h *Handler) FileUploadHandler(w http.ResponseWriter, r *http.Request) { func (h *Handler) handleFileUpload(podName, podFileName, sessionId string, fileSize int64, f multipart.File, podPath, compression string, blockSize uint32, overwrite bool) error { defer f.Close() - return h.dfsAPI.UploadFile(podName, podFileName, sessionId, fileSize, f, podPath, compression, blockSize, overwrite) + return h.dfsAPI.UploadFile(podName, podFileName, sessionId, fileSize, f, podPath, compression, blockSize, 0, overwrite) } diff --git a/pkg/api/handler.go b/pkg/api/handler.go index 30a88093..14093b8f 100644 --- a/pkg/api/handler.go +++ b/pkg/api/handler.go @@ -36,8 +36,8 @@ type Handler struct { } // New -func New(ctx context.Context, beeApi, cookieDomain, postageBlockId string, whitelistedOrigins []string, ensConfig *contracts.Config, logger logging.Logger) (*Handler, error) { - api, err := dfs.NewDfsAPI(beeApi, postageBlockId, ensConfig, logger) +func New(ctx context.Context, beeApi, cookieDomain, postageBlockId string, whitelistedOrigins []string, ensConfig *contracts.ENSConfig, subscriptionConfig *contracts.SubscriptionConfig, logger logging.Logger) (*Handler, error) { + api, err := dfs.NewDfsAPI(beeApi, postageBlockId, ensConfig, subscriptionConfig, logger) if err != nil { return nil, err diff --git a/pkg/api/pod_open.go b/pkg/api/pod_open.go index 664da80d..ed4c8b56 100644 --- a/pkg/api/pod_open.go +++ b/pkg/api/pod_open.go @@ -145,20 +145,5 @@ func (h *Handler) PodOpenAsyncHandler(w http.ResponseWriter, r *http.Request) { jsonhttp.BadRequest(w, &response{Message: "pod open: \"cookie-id\" parameter missing in cookie"}) return } - - // open pod - _, err = h.dfsAPI.OpenPodAsync(r.Context(), pod, sessionId) - if err != nil { - if err == dfs.ErrUserNotLoggedIn || - err == p.ErrInvalidPodName { - h.logger.Errorf("pod open: %v", err) - jsonhttp.NotFound(w, &response{Message: "pod open: " + err.Error()}) - return - } - h.logger.Errorf("pod open: %v", err) - jsonhttp.InternalServerError(w, &response{Message: "pod open: " + err.Error()}) - return - } - - jsonhttp.OK(w, &response{Message: "pod opened successfully"}) + jsonhttp.BadRequest(w, &response{Message: "pod/open-async: deprecated"}) } diff --git a/pkg/api/public.go b/pkg/api/public.go new file mode 100644 index 00000000..5c3325eb --- /dev/null +++ b/pkg/api/public.go @@ -0,0 +1,324 @@ +package api + +import ( + "io" + "mime" + "net/http" + "path/filepath" + "strconv" + "strings" + + "github.com/fairdatasociety/fairOS-dfs/pkg/collection" + "github.com/fairdatasociety/fairOS-dfs/pkg/dir" + "github.com/fairdatasociety/fairOS-dfs/pkg/file" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" + "github.com/gorilla/mux" + "resenje.org/jsonhttp" +) + +// PublicPodGetFileHandler godoc +// +// @Summary download file from a shared pod +// @Description PodReceiveInfoHandler is the api handler to download file from a shared pod +// @Tags public +// @Accept json +// @Produce json +// @Param sharingRef query string true "pod sharing reference" +// @Param filePath query string true "file location in the pod" +// @Success 200 {array} byte +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /public-file [get] +func (h *Handler) PublicPodGetFileHandler(w http.ResponseWriter, r *http.Request) { + keys, ok := r.URL.Query()["sharingRef"] + if !ok || len(keys[0]) < 1 { + h.logger.Errorf("public pod file download: \"sharingRef\" argument missing") + jsonhttp.BadRequest(w, "public pod file download: \"sharingRef\" argument missing") + return + } + + sharingRefString := keys[0] + if sharingRefString == "" { + h.logger.Errorf("public pod file download: \"sharingRef\" argument missing") + jsonhttp.BadRequest(w, "public pod file download: \"sharingRef\" argument missing") + return + } + + ref, err := utils.ParseHexReference(sharingRefString) + if err != nil { + h.logger.Errorf("public pod file download: invalid reference: ", err) + jsonhttp.BadRequest(w, "public pod file download: invalid reference:"+err.Error()) + return + } + keys, ok = r.URL.Query()["filePath"] + if !ok || len(keys[0]) < 1 { + h.logger.Errorf("public pod file download: \"filePath\" argument missing") + jsonhttp.BadRequest(w, "public pod file download: \"filePath\" argument missing") + return + } + filePath := keys[0] + if filePath == "" { + h.logger.Errorf("public pod file download: \"filePath\" argument missing") + jsonhttp.BadRequest(w, "public pod file download: \"filePath\" argument missing") + return + } + + shareInfo, err := h.dfsAPI.PublicPodReceiveInfo(ref) + if err != nil { + h.logger.Errorf("public pod file download: %v", err) + jsonhttp.InternalServerError(w, "public pod file download: "+err.Error()) + return + } + + reader, size, err := h.dfsAPI.PublicPodFileDownload(shareInfo, filePath) + if err != nil { + h.logger.Errorf("public pod file download: %v", err) + jsonhttp.InternalServerError(w, "public pod file download: "+err.Error()) + return + } + + defer reader.Close() + + sizeString := strconv.FormatUint(size, 10) + w.Header().Set("Content-Length", sizeString) + + _, err = io.Copy(w, reader) + if err != nil { + h.logger.Errorf("download: %v", err) + w.Header().Set("Content-Type", " application/json") + jsonhttp.InternalServerError(w, "public pod file download: "+err.Error()) + } +} + +// PublicPodFilePathHandler godoc +// +// @Summary download file from a shared pod +// @Description PublicPodFilePathHandler is the api handler to download file from a shared pod +// @Tags public +// @Accept json +// @Produce json +// @Success 200 {array} byte +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /public/{ref}/{file} [get] +func (h *Handler) PublicPodFilePathHandler(w http.ResponseWriter, r *http.Request) { + + params := mux.Vars(r) + sharingRefString, ok := params["ref"] + if !ok { + h.logger.Errorf("public pod file download: \"sharingRef\" argument missing") + jsonhttp.BadRequest(w, "public pod file download: \"sharingRef\" argument missing") + return + } + if sharingRefString == "" { + h.logger.Errorf("public pod file download: \"sharingRef\" argument missing") + jsonhttp.BadRequest(w, "public pod file download: \"sharingRef\" argument missing") + return + } + + ref, err := utils.ParseHexReference(sharingRefString) + if err != nil { + h.logger.Errorf("public pod file download: invalid reference: ", err) + jsonhttp.BadRequest(w, "public pod file download: invalid reference:"+err.Error()) + return + } + filePath := params["file"] + if filePath == "" { + filePath = "/index.html" + } else { + filePath = "/" + filePath + } + + shareInfo, err := h.dfsAPI.PublicPodReceiveInfo(ref) + if err != nil { + h.logger.Errorf("public pod file download: %v", err) + jsonhttp.InternalServerError(w, "public pod file download: "+err.Error()) + return + } + contentType := mime.TypeByExtension(filepath.Ext(filePath)) + reader, size, err := h.dfsAPI.PublicPodFileDownload(shareInfo, filePath) + if err != nil { + h.logger.Errorf("public pod file download: %v", err) + jsonhttp.InternalServerError(w, "public pod file download: "+err.Error()) + return + } + + defer reader.Close() + w.Header().Set("Content-Length", strconv.Itoa(int(size))) + w.Header().Set("Content-Type", contentType) + if strings.HasPrefix(filePath, "static/") { + w.Header().Set("Cache-Control", "public, max-age=31536000") + } + _, err = io.Copy(w, reader) + if err != nil { + h.logger.Errorf("download: %v", err) + w.Header().Set("Content-Type", " application/json") + jsonhttp.InternalServerError(w, "public pod file download: "+err.Error()) + } +} + +// PublicPodGetDirHandler godoc +// +// @Summary List directory content +// @Description PublicPodGetDirHandler is the api handler to list content of a directory from a public pod +// @Tags public +// @Accept json +// @Produce json +// @Param sharingRef query string true "pod sharing reference" +// @Param dirPath query string true "dir location in the pod" +// @Success 200 {object} ListFileResponse +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /public-dir [get] +func (h *Handler) PublicPodGetDirHandler(w http.ResponseWriter, r *http.Request) { + keys, ok := r.URL.Query()["sharingRef"] + if !ok || len(keys[0]) < 1 { + h.logger.Errorf("public pod file download: \"sharingRef\" argument missing") + jsonhttp.BadRequest(w, "public pod file download: \"sharingRef\" argument missing") + return + } + + sharingRefString := keys[0] + if sharingRefString == "" { + h.logger.Errorf("public pod file download: \"sharingRef\" argument missing") + jsonhttp.BadRequest(w, "public pod file download: \"sharingRef\" argument missing") + return + } + + ref, err := utils.ParseHexReference(sharingRefString) + if err != nil { + h.logger.Errorf("public pod file download: invalid reference: ", err) + jsonhttp.BadRequest(w, "public pod file download: invalid reference:"+err.Error()) + return + } + keys, ok = r.URL.Query()["dirPath"] + if !ok || len(keys[0]) < 1 { + h.logger.Errorf("public pod file download: \"filePath\" argument missing") + jsonhttp.BadRequest(w, "public pod file download: \"filePath\" argument missing") + return + } + dirPath := keys[0] + if dirPath == "" { + h.logger.Errorf("public pod file download: \"filePath\" argument missing") + jsonhttp.BadRequest(w, "public pod file download: \"filePath\" argument missing") + return + } + + shareInfo, err := h.dfsAPI.PublicPodReceiveInfo(ref) + if err != nil { + h.logger.Errorf("public pod file download: %v", err) + jsonhttp.InternalServerError(w, "public pod file download: "+err.Error()) + return + } + + dEntries, fEntries, err := h.dfsAPI.PublicPodDisLs(shareInfo, dirPath) + if err != nil { + h.logger.Errorf("public pod file download: %v", err) + jsonhttp.InternalServerError(w, "public pod file download: "+err.Error()) + return + } + + if dEntries == nil { + dEntries = make([]dir.Entry, 0) + } + if fEntries == nil { + fEntries = make([]file.Entry, 0) + } + w.Header().Set("Content-Type", "application/json") + jsonhttp.OK(w, &ListFileResponse{ + Directories: dEntries, + Files: fEntries, + }) +} + +// PublicPodKVEntryGetHandler godoc +// +// @Summary get key from public pod +// @Description PublicPodKVEntryGetHandler is the api handler to get key from key value store from a public pod +// @Tags public +// @Accept json +// @Produce json +// @Param sharingRef query string true "pod sharing reference" +// @Param tableName query string true "table name" +// @Param key query string true "key to look up" +// @Success 200 {object} KVResponse +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /public-kv [get] +func (h *Handler) PublicPodKVEntryGetHandler(w http.ResponseWriter, r *http.Request) { + keys, ok := r.URL.Query()["sharingRef"] + if !ok || len(keys[0]) < 1 { + h.logger.Errorf("public pod kv get: \"sharingRef\" argument missing") + jsonhttp.BadRequest(w, "public pod kv get: \"sharingRef\" argument missing") + return + } + + sharingRefString := keys[0] + if sharingRefString == "" { + h.logger.Errorf("public pod kv get: \"sharingRef\" argument missing") + jsonhttp.BadRequest(w, "public pod kv get: \"sharingRef\" argument missing") + return + } + + ref, err := utils.ParseHexReference(sharingRefString) + if err != nil { + h.logger.Errorf("public pod kv get: invalid reference: ", err) + jsonhttp.BadRequest(w, "public pod kv get: invalid reference:"+err.Error()) + return + } + + keys, ok = r.URL.Query()["tableName"] + if !ok || len(keys[0]) < 1 { + h.logger.Errorf("public pod kv get: \"tableName\" argument missing") + jsonhttp.BadRequest(w, &response{Message: "public pod kv get: \"tableName\" argument missing"}) + return + } + name := keys[0] + if name == "" { + h.logger.Errorf("public pod kv get: \"tableName\" argument missing") + jsonhttp.BadRequest(w, &response{Message: "public pod kv get: \"tableName\" argument missing"}) + return + } + + keys, ok = r.URL.Query()["key"] + if !ok || len(keys[0]) < 1 { + h.logger.Errorf("public pod kv get: \"key\" argument missing") + jsonhttp.BadRequest(w, &response{Message: "public pod kv get: \"key\" argument missing"}) + return + } + key := keys[0] + if key == "" { + h.logger.Errorf("public pod kv get: \"key\" argument missing") + jsonhttp.BadRequest(w, &response{Message: "public pod kv get: \"key\" argument missing"}) + return + } + + shareInfo, err := h.dfsAPI.PublicPodReceiveInfo(ref) + if err != nil { + h.logger.Errorf("public pod kv get: %v", err) + jsonhttp.InternalServerError(w, "public pod kv get: "+err.Error()) + return + } + + columns, data, err := h.dfsAPI.PublicPodKVEntryGet(shareInfo, name, key) + if err != nil { + h.logger.Errorf("public pod kv get: %v", err) + if err == collection.ErrEntryNotFound { + jsonhttp.NotFound(w, &response{Message: "public pod kv get: " + err.Error()}) + return + } + jsonhttp.InternalServerError(w, &response{Message: "public pod kv get: " + err.Error()}) + return + } + + var resp KVResponse + if columns != nil { + resp.Keys = columns + } else { + resp.Keys = []string{key} + } + resp.Values = data + + w.Header().Set("Content-Type", "application/json") + jsonhttp.OK(w, &resp) +} diff --git a/pkg/api/ws.go b/pkg/api/ws.go index 56567ffc..c24eebfe 100644 --- a/pkg/api/ws.go +++ b/pkg/api/ws.go @@ -693,7 +693,7 @@ func (h *Handler) handleEvents(conn *websocket.Conn) error { respondWithError(res, err) continue } - err = h.dfsAPI.Mkdir(fsReq.PodName, fsReq.DirectoryPath, sessionID) + err = h.dfsAPI.Mkdir(fsReq.PodName, fsReq.DirectoryPath, sessionID, 0) if err != nil { respondWithError(res, err) continue @@ -1076,7 +1076,7 @@ func (h *Handler) handleEvents(conn *websocket.Conn) error { respondWithError(res, err) continue } - err = h.dfsAPI.UploadFile(fsReq.PodName, fileName, sessionID, int64(len(data.Bytes())), data, fsReq.DirPath, compression, uint32(bs), fsReq.Overwrite) + err = h.dfsAPI.UploadFile(fsReq.PodName, fileName, sessionID, int64(len(data.Bytes())), data, fsReq.DirPath, compression, uint32(bs), 0, fsReq.Overwrite) if err != nil { respondWithError(res, err) continue @@ -1138,12 +1138,8 @@ func (h *Handler) handleEvents(conn *websocket.Conn) error { respondWithError(res, err) continue } - sharingRef, err := utils.ParseSharingReference(fsReq.SharingReference) - if err != nil { - respondWithError(res, err) - continue - } - filePath, err := h.dfsAPI.ReceiveFile(fsReq.PodName, fsReq.DirectoryPath, sharingRef, sessionID) + + filePath, err := h.dfsAPI.ReceiveFile(fsReq.PodName, fsReq.DirectoryPath, fsReq.SharingReference, sessionID) if err != nil { respondWithError(res, err) continue @@ -1175,12 +1171,7 @@ func (h *Handler) handleEvents(conn *websocket.Conn) error { respondWithError(res, err) continue } - sharingRef, err := utils.ParseSharingReference(fsReq.SharingReference) - if err != nil { - respondWithError(res, err) - continue - } - receiveInfo, err := h.dfsAPI.ReceiveInfo(sessionID, sharingRef) + receiveInfo, err := h.dfsAPI.ReceiveInfo(sessionID, fsReq.SharingReference) if err != nil { respondWithError(res, err) continue diff --git a/pkg/blockstore/bee/client.go b/pkg/blockstore/bee/client.go index 55d96ec7..6ad979f2 100644 --- a/pkg/blockstore/bee/client.go +++ b/pkg/blockstore/bee/client.go @@ -46,6 +46,7 @@ const ( healthUrl = "/health" chunkUploadDownloadUrl = "/chunks" bytesUploadDownloadUrl = "/bytes" + bzzUrl = "/bzz" tagsUrl = "/tags" pinsUrl = "/pins/" _ = pinsUrl @@ -53,7 +54,8 @@ const ( swarmEncryptHeader = "Swarm-Encrypt" swarmPostageBatchId = "Swarm-Postage-Batch-Id" //swarmDeferredUploadHeader = "Swarm-Deferred-Upload" - swarmTagHeader = "Swarm-Tag" + swarmTagHeader = "Swarm-Tag" + contentTypeHeader = "Content-Type" ) // Client is a bee http client that satisfies blockstore.Client @@ -67,6 +69,7 @@ type Client struct { postageBlockId string logger logging.Logger isProxy bool + shouldPin bool } func hashFunc() hash.Hash { @@ -95,7 +98,7 @@ type beeError struct { } // NewBeeClient creates a new client which connects to the Swarm bee node to access the Swarm network. -func NewBeeClient(apiUrl, postageBlockId string, logger logging.Logger) *Client { +func NewBeeClient(apiUrl, postageBlockId string, shouldPin bool, logger logging.Logger) *Client { p := bmtlegacy.NewTreePool(hashFunc, swarm.Branches, bmtlegacy.PoolSize) cache, err := lru.New(chunkCacheSize) if err != nil { @@ -119,6 +122,7 @@ func NewBeeClient(apiUrl, postageBlockId string, logger logging.Logger) *Client downloadBlockCache: downloadBlockCache, postageBlockId: postageBlockId, logger: logger, + shouldPin: shouldPin, } } @@ -190,7 +194,9 @@ func (s *Client) UploadSOC(owner, id, signature string, data []byte) (address [] // TODO change this in the future when we have some alternative to pin SOC // This is a temporary fix to force soc pinning - req.Header.Set(swarmPinHeader, "true") + if s.shouldPin { + req.Header.Set(swarmPinHeader, "true") + } response, err := s.client.Do(req) if err != nil { @@ -227,12 +233,12 @@ func (s *Client) UploadSOC(owner, id, signature string, data []byte) (address [] "reference": addrResp.Reference.String(), "duration": time.Since(to).String(), } - s.logger.WithFields(fields).Log(logrus.DebugLevel, "upload chunk: ") + s.logger.WithFields(fields).Log(logrus.DebugLevel, "upload soc: ") return addrResp.Reference.Bytes(), nil } // UploadChunk uploads a chunk to Swarm network. -func (s *Client) UploadChunk(ch swarm.Chunk, pin bool) (address []byte, err error) { +func (s *Client) UploadChunk(ch swarm.Chunk) (address []byte, err error) { to := time.Now() fullUrl := fmt.Sprintf(s.url + chunkUploadDownloadUrl) req, err := http.NewRequest(http.MethodPost, fullUrl, bytes.NewBuffer(ch.Data())) @@ -240,7 +246,7 @@ func (s *Client) UploadChunk(ch swarm.Chunk, pin bool) (address []byte, err erro return nil, err } - if pin { + if s.shouldPin { req.Header.Set(swarmPinHeader, "true") } @@ -333,7 +339,7 @@ func (s *Client) DownloadChunk(ctx context.Context, address []byte) (data []byte } // UploadBlob uploads a binary blob of data to Swarm network. It also optionally pins and encrypts the data. -func (s *Client) UploadBlob(data []byte, tag uint32, pin, encrypt bool) (address []byte, err error) { +func (s *Client) UploadBlob(data []byte, tag uint32, encrypt bool) (address []byte, err error) { to := time.Now() // return the ref if this data is already in swarm @@ -347,7 +353,7 @@ func (s *Client) UploadBlob(data []byte, tag uint32, pin, encrypt bool) (address return nil, err } - if pin { + if s.shouldPin { req.Header.Set(swarmPinHeader, "true") } @@ -458,6 +464,110 @@ func (s *Client) DownloadBlob(address []byte) ([]byte, int, error) { return respData, response.StatusCode, nil } +// UploadBzz uploads a file through bzz api +func (s *Client) UploadBzz(data []byte, fileName string) (address []byte, err error) { + to := time.Now() + + fullUrl := s.url + bzzUrl + "?name=" + fileName + req, err := http.NewRequest(http.MethodPost, fullUrl, bytes.NewBuffer(data)) + if err != nil { + return nil, err + } + + req.Header.Set(swarmPostageBatchId, s.postageBlockId) + req.Header.Set(contentTypeHeader, "application/json") + + response, err := s.client.Do(req) + if err != nil { + return nil, err + } + defer response.Body.Close() + + req.Close = true + + respData, err := io.ReadAll(response.Body) + if err != nil { + return nil, errors.New("error downloading bzz") + } + + if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated { + var beeErr *beeError + err = json.Unmarshal(respData, &beeErr) + if err != nil { + return nil, errors.New(string(respData)) + } + return nil, errors.New(beeErr.Message) + } + + var resp bytesPostResponse + err = json.Unmarshal(respData, &resp) + + fields := logrus.Fields{ + "reference": resp.Reference.String(), + "size": len(respData), + "duration": time.Since(to).String(), + } + s.logger.WithFields(fields).Log(logrus.DebugLevel, "upload bzz: ") + + // add the data and ref if it is not in cache + if !s.inBlockCache(s.downloadBlockCache, resp.Reference.String()) { + s.addToBlockCache(s.downloadBlockCache, resp.Reference.String(), data) + } + return resp.Reference.Bytes(), nil +} + +// DownloadBzz downloads bzz data from the Swarm network. +func (s *Client) DownloadBzz(address []byte) ([]byte, int, error) { + to := time.Now() + + // return the data if this address is already in cache + addrString := swarm.NewAddress(address).String() + if s.inBlockCache(s.downloadBlockCache, addrString) { + return s.getFromBlockCache(s.downloadBlockCache, addrString), 200, nil + } + + fullUrl := s.url + bzzUrl + "/" + addrString + req, err := http.NewRequest(http.MethodGet, fullUrl, http.NoBody) + if err != nil { + return nil, http.StatusNotFound, err + } + + response, err := s.client.Do(req) + if err != nil { + return nil, http.StatusNotFound, err + } + defer response.Body.Close() + + req.Close = true + + respData, err := io.ReadAll(response.Body) + if err != nil { + return nil, response.StatusCode, errors.New("error downloading bzz") + } + + if response.StatusCode != http.StatusOK { + var beeErr *beeError + err = json.Unmarshal(respData, &beeErr) + if err != nil { + return nil, response.StatusCode, errors.New(string(respData)) + } + return nil, response.StatusCode, errors.New(beeErr.Message) + } + + fields := logrus.Fields{ + "reference": addrString, + "size": len(respData), + "duration": time.Since(to).String(), + } + s.logger.WithFields(fields).Log(logrus.DebugLevel, "download bzz: ") + + // add the data and ref if it is not in cache + if !s.inBlockCache(s.downloadBlockCache, addrString) { + s.addToBlockCache(s.downloadBlockCache, addrString, respData) + } + return respData, response.StatusCode, nil +} + // DeleteReference unpins a reference so that it will be garbage collected by the Swarm network. func (s *Client) DeleteReference(address []byte) error { // TODO uncomment after unpinning is fixed diff --git a/pkg/blockstore/bee/mock/client.go b/pkg/blockstore/bee/mock/client.go index 05b20add..04e01ee6 100644 --- a/pkg/blockstore/bee/mock/client.go +++ b/pkg/blockstore/bee/mock/client.go @@ -89,7 +89,7 @@ func (m *BeeClient) UploadSOC(owner, id, signature string, data []byte) (address } // UploadChunk into swarm -func (m *BeeClient) UploadChunk(ch swarm.Chunk, _ bool) (address []byte, err error) { +func (m *BeeClient) UploadChunk(ch swarm.Chunk) (address []byte, err error) { m.storerMu.Lock() defer m.storerMu.Unlock() m.storer[ch.Address().String()] = ch.Data() @@ -107,7 +107,7 @@ func (m *BeeClient) DownloadChunk(_ context.Context, address []byte) (data []byt } // UploadBlob into swarm -func (m *BeeClient) UploadBlob(data []byte, tag uint32, _, _ bool) (address []byte, err error) { +func (m *BeeClient) UploadBlob(data []byte, tag uint32, _ bool) (address []byte, err error) { m.storerMu.Lock() defer m.storerMu.Unlock() address = make([]byte, 32) @@ -132,6 +132,16 @@ func (m *BeeClient) DownloadBlob(address []byte) ([]byte, int, error) { return nil, http.StatusInternalServerError, fmt.Errorf("error downloading data") } +// UploadBzz downloads data to bzz api from the Swarm network. +func (m *BeeClient) UploadBzz(_ []byte, _ string) ([]byte, error) { + return nil, nil +} + +// DownloadBzz downloads bzz data from the Swarm network. +func (m *BeeClient) DownloadBzz(_ []byte) ([]byte, int, error) { + return nil, 0, nil +} + // DeleteReference unpins chunk in swarm func (m *BeeClient) DeleteReference(address []byte) error { m.storerMu.Lock() diff --git a/pkg/blockstore/client.go b/pkg/blockstore/client.go index fb5d464c..97fcc943 100644 --- a/pkg/blockstore/client.go +++ b/pkg/blockstore/client.go @@ -26,10 +26,12 @@ import ( type Client interface { CheckConnection() bool UploadSOC(owner string, id string, signature string, data []byte) (address []byte, err error) - UploadChunk(ch swarm.Chunk, pin bool) (address []byte, err error) - UploadBlob(data []byte, tag uint32, pin bool, encrypt bool) (address []byte, err error) + UploadChunk(ch swarm.Chunk) (address []byte, err error) + UploadBlob(data []byte, tag uint32, encrypt bool) (address []byte, err error) + UploadBzz(data []byte, fileName string) (address []byte, err error) DownloadChunk(ctx context.Context, address []byte) (data []byte, err error) DownloadBlob(address []byte) (data []byte, respCode int, err error) + DownloadBzz(address []byte) (data []byte, respCode int, err error) DeleteReference(address []byte) error CreateTag(address []byte) (uint32, error) GetTag(tag uint32) (int64, int64, int64, error) diff --git a/pkg/collection/document.go b/pkg/collection/document.go index 2aa70b0d..750e10ec 100644 --- a/pkg/collection/document.go +++ b/pkg/collection/document.go @@ -633,7 +633,7 @@ func (d *Document) Put(dbName string, doc []byte) error { } // upload the document - ref, err := d.client.UploadBlob(doc, 0, true, true) + ref, err := d.client.UploadBlob(doc, 0, true) if err != nil { // skipcq: TCV-001 d.logger.Errorf("inserting in to document db: ", err.Error()) return err @@ -1419,7 +1419,7 @@ func (d *Document) DocBatchPut(docBatch *DocBatch, doc []byte, index int64) erro } // upload the document - ref, err = d.client.UploadBlob(doc, 0, true, true) + ref, err = d.client.UploadBlob(doc, 0, true) if err != nil { // skipcq: TCV-001 d.logger.Errorf("inserting in batch: ", err.Error()) return err diff --git a/pkg/collection/index.go b/pkg/collection/index.go index 86003839..b1dc67cd 100644 --- a/pkg/collection/index.go +++ b/pkg/collection/index.go @@ -126,7 +126,7 @@ func CreateIndex(podName, collectionName, indexName, encryptionPassword string, return ErrManifestUnmarshall } - ref, err := client.UploadBlob(data, 0, true, true) + ref, err := client.UploadBlob(data, 0, true) if err != nil { // skipcq: TCV-001 return ErrManifestUnmarshall } @@ -281,7 +281,7 @@ func (idx *Index) updateManifest(manifest *Manifest, encryptionPassword string) return ErrManifestUnmarshall } - ref, err := idx.client.UploadBlob(data, 0, true, true) + ref, err := idx.client.UploadBlob(data, 0, true) if err != nil { // skipcq: TCV-001 return ErrManifestUnmarshall } @@ -303,7 +303,7 @@ func (idx *Index) storeManifest(manifest *Manifest, encryptionPassword string) e logStr := fmt.Sprintf("storing Manifest: %s, data len = %d", manifest.Name, len(data)) idx.logger.Debug(logStr) - ref, err := idx.client.UploadBlob(data, 0, true, true) + ref, err := idx.client.UploadBlob(data, 0, true) //TODO: once the tags issue is fixed i bytes. // remove the error string check if err != nil { // skipcq: TCV-001 diff --git a/pkg/collection/index_api_test.go b/pkg/collection/index_api_test.go index 8eb35389..071c3f3e 100644 --- a/pkg/collection/index_api_test.go +++ b/pkg/collection/index_api_test.go @@ -141,7 +141,7 @@ func TestIndexAPI(t *testing.T) { } func addDoc(t *testing.T, key string, value []byte, index *collection.Index, client *mock.BeeClient, apnd bool) { - ref, err := client.UploadBlob(value, 0, false, false) + ref, err := client.UploadBlob(value, 0, false) if err != nil { t.Fatalf("could not add doc %s:%s, %v", key, value, err) } @@ -277,7 +277,7 @@ func addBatchDocs(t *testing.T, batch *collection.Batch, client *mock.BeeClient) // add the documents for k, v := range kvMap { - ref, err := client.UploadBlob(v, 0, false, false) + ref, err := client.UploadBlob(v, 0, false) if err != nil { t.Fatalf("could not add doc %s:%s, %v", k, ref, err) } diff --git a/pkg/collection/kv.go b/pkg/collection/kv.go index bb006237..391dd1ae 100644 --- a/pkg/collection/kv.go +++ b/pkg/collection/kv.go @@ -264,7 +264,7 @@ func (kv *KeyValue) KVPut(name, key string, value []byte) error { } return table.index.PutNumber(fkey, value, NumberIndex, false) case BytesIndex: - ref, err := kv.client.UploadBlob(value, 0, true, true) + ref, err := kv.client.UploadBlob(value, 0, true) if err != nil { // skipcq: TCV-001 return err } diff --git a/pkg/contracts/config.go b/pkg/contracts/config.go index cc04f765..2ebe9bf8 100644 --- a/pkg/contracts/config.go +++ b/pkg/contracts/config.go @@ -1,7 +1,7 @@ package contracts -// Config handles the ENS configuration -type Config struct { +// ENSConfig handles the ENS configuration +type ENSConfig struct { ChainID string ENSRegistryAddress string FDSRegistrarAddress string @@ -10,24 +10,31 @@ type Config struct { ProviderBackend string } +// SubscriptionConfig handles the Subscription Management +type SubscriptionConfig struct { + RPC string + DataHubAddress string +} + // TestnetConfig defines the configuration for goerli testnet -func TestnetConfig() *Config { - return &Config{ +func TestnetConfig() (*ENSConfig, *SubscriptionConfig) { + e := &ENSConfig{ ChainID: "5", ENSRegistryAddress: "0x42B22483e3c8dF794f351939620572d1a3193c12", FDSRegistrarAddress: "0xF4C9Cd25031E3BB8c5618299bf35b349c1aAb6A9", PublicResolverAddress: "0xbfeCC6c32B224F7D0026ac86506Fe40A9607BD14", ProviderDomain: "fds", } + return e, nil } // PlayConfig defines the configuration for fdp-play -func PlayConfig() *Config { - return &Config{ +func PlayConfig() (*ENSConfig, *SubscriptionConfig) { + return &ENSConfig{ ChainID: "4020", ENSRegistryAddress: "0xDb56f2e9369E0D7bD191099125a3f6C370F8ed15", FDSRegistrarAddress: "0xA94B7f0465E98609391C623d0560C5720a3f2D33", PublicResolverAddress: "0xFC628dd79137395F3C9744e33b1c5DE554D94882", ProviderDomain: "fds", - } + }, nil } diff --git a/pkg/contracts/datahub/Datahub.go b/pkg/contracts/datahub/Datahub.go new file mode 100644 index 00000000..7910b61f --- /dev/null +++ b/pkg/contracts/datahub/Datahub.go @@ -0,0 +1,2368 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package datahub + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// DataHubActiveBid is an auto generated low-level Go binding around an user-defined struct. +type DataHubActiveBid struct { + Seller common.Address + RequestHash [32]byte +} + +// DataHubCategory is an auto generated low-level Go binding around an user-defined struct. +type DataHubCategory struct { + SubIdxs []uint64 +} + +// DataHubSub is an auto generated low-level Go binding around an user-defined struct. +type DataHubSub struct { + SubHash [32]byte + FdpSellerNameHash [32]byte + Seller common.Address + SwarmLocation [32]byte + Price *big.Int + Active bool + Earned *big.Int + Bids uint32 + Sells uint32 + Reports uint32 + DaysValid uint16 +} + +// DataHubSubItem is an auto generated low-level Go binding around an user-defined struct. +type DataHubSubItem struct { + SubHash [32]byte + UnlockKeyLocation [32]byte + ValidTill *big.Int +} + +// DataHubSubRequest is an auto generated low-level Go binding around an user-defined struct. +type DataHubSubRequest struct { + FdpBuyerNameHash [32]byte + Buyer common.Address + SubHash [32]byte + RequestHash [32]byte +} + +// DatahubMetaData contains all meta data concerning the Datahub contract. +var DatahubMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROLE_REPORTER\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fdpBuyerNameHash\",\"type\":\"bytes32\"}],\"name\":\"bidSub\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"}],\"name\":\"enableSub\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feesCollected\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundsBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundsTransfer\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getActiveBidAt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"seller\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"requestHash\",\"type\":\"bytes32\"}],\"internalType\":\"structDataHub.ActiveBid\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getActiveBids\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"seller\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"requestHash\",\"type\":\"bytes32\"}],\"internalType\":\"structDataHub.ActiveBid[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"requestHash\",\"type\":\"bytes32\"}],\"name\":\"getActiveBidsByHash\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"seller\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"requestHash\",\"type\":\"bytes32\"}],\"internalType\":\"structDataHub.ActiveBid\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getAllSubItems\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"unlockKeyLocation\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"validTill\",\"type\":\"uint256\"}],\"internalType\":\"structDataHub.SubItem[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nameHash\",\"type\":\"bytes32\"}],\"name\":\"getAllSubItemsForNameHash\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"unlockKeyLocation\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"validTill\",\"type\":\"uint256\"}],\"internalType\":\"structDataHub.SubItem[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"category\",\"type\":\"bytes32\"}],\"name\":\"getCategory\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64[]\",\"name\":\"subIdxs\",\"type\":\"uint64[]\"}],\"internalType\":\"structDataHub.Category\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getListedSubs\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nameHash\",\"type\":\"bytes32\"}],\"name\":\"getNameHashSubItems\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getPortableAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"}],\"name\":\"getSubBy\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fdpSellerNameHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"seller\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"swarmLocation\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"earned\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"bids\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"sells\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"reports\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"daysValid\",\"type\":\"uint16\"}],\"internalType\":\"structDataHub.Sub\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getSubByIndex\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fdpSellerNameHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"seller\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"swarmLocation\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"earned\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"bids\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"sells\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"reports\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"daysValid\",\"type\":\"uint16\"}],\"internalType\":\"structDataHub.Sub\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"forAddress\",\"type\":\"address\"}],\"name\":\"getSubInfoBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getSubItemAt\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"unlockKeyLocation\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"validTill\",\"type\":\"uint256\"}],\"internalType\":\"structDataHub.SubItem\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"getSubItems\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"unlockKeyLocation\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"validTill\",\"type\":\"uint256\"}],\"internalType\":\"structDataHub.SubItem[]\",\"name\":\"items\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"last\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getSubRequestAt\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"fdpBuyerNameHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"buyer\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"requestHash\",\"type\":\"bytes32\"}],\"internalType\":\"structDataHub.SubRequest\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"requestHash\",\"type\":\"bytes32\"}],\"name\":\"getSubRequestByHash\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"fdpBuyerNameHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"buyer\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"requestHash\",\"type\":\"bytes32\"}],\"internalType\":\"structDataHub.SubRequest\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getSubRequests\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"fdpBuyerNameHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"buyer\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"requestHash\",\"type\":\"bytes32\"}],\"internalType\":\"structDataHub.SubRequest[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"}],\"name\":\"getSubSubscribers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSubs\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fdpSellerNameHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"seller\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"swarmLocation\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"earned\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"bids\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"sells\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"reports\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"daysValid\",\"type\":\"uint16\"}],\"internalType\":\"structDataHub.Sub[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getUserStats\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"numSubRequests\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numSubItems\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numActiveBids\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numListedSubs\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"inEscrow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"fdpSellerNameHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"dataSwarmLocation\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"category\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"podAddress\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"daysValid\",\"type\":\"uint16\"}],\"name\":\"listSub\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"marketFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minListingFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"requestHash\",\"type\":\"bytes32\"}],\"name\":\"removeUserActiveBid\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"}],\"name\":\"reportSub\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"requestHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"encryptedKeyLocation\",\"type\":\"bytes32\"}],\"name\":\"sellSub\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newListingFee\",\"type\":\"uint256\"}],\"name\":\"setListingFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setPortableAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"subscriptionIds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"subscriptions\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"subHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fdpSellerNameHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"seller\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"swarmLocation\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"earned\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"bids\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"sells\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"reports\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"daysValid\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", +} + +// DatahubABI is the input ABI used to generate the binding from. +// Deprecated: Use DatahubMetaData.ABI instead. +var DatahubABI = DatahubMetaData.ABI + +// Datahub is an auto generated Go binding around an Ethereum contract. +type Datahub struct { + DatahubCaller // Read-only binding to the contract + DatahubTransactor // Write-only binding to the contract + DatahubFilterer // Log filterer for contract events +} + +// DatahubCaller is an auto generated read-only Go binding around an Ethereum contract. +type DatahubCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DatahubTransactor is an auto generated write-only Go binding around an Ethereum contract. +type DatahubTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DatahubFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type DatahubFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DatahubSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type DatahubSession struct { + Contract *Datahub // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// DatahubCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type DatahubCallerSession struct { + Contract *DatahubCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// DatahubTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type DatahubTransactorSession struct { + Contract *DatahubTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// DatahubRaw is an auto generated low-level Go binding around an Ethereum contract. +type DatahubRaw struct { + Contract *Datahub // Generic contract binding to access the raw methods on +} + +// DatahubCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type DatahubCallerRaw struct { + Contract *DatahubCaller // Generic read-only contract binding to access the raw methods on +} + +// DatahubTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type DatahubTransactorRaw struct { + Contract *DatahubTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewDatahub creates a new instance of Datahub, bound to a specific deployed contract. +func NewDatahub(address common.Address, backend bind.ContractBackend) (*Datahub, error) { + contract, err := bindDatahub(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Datahub{DatahubCaller: DatahubCaller{contract: contract}, DatahubTransactor: DatahubTransactor{contract: contract}, DatahubFilterer: DatahubFilterer{contract: contract}}, nil +} + +// NewDatahubCaller creates a new read-only instance of Datahub, bound to a specific deployed contract. +func NewDatahubCaller(address common.Address, caller bind.ContractCaller) (*DatahubCaller, error) { + contract, err := bindDatahub(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &DatahubCaller{contract: contract}, nil +} + +// NewDatahubTransactor creates a new write-only instance of Datahub, bound to a specific deployed contract. +func NewDatahubTransactor(address common.Address, transactor bind.ContractTransactor) (*DatahubTransactor, error) { + contract, err := bindDatahub(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &DatahubTransactor{contract: contract}, nil +} + +// NewDatahubFilterer creates a new log filterer instance of Datahub, bound to a specific deployed contract. +func NewDatahubFilterer(address common.Address, filterer bind.ContractFilterer) (*DatahubFilterer, error) { + contract, err := bindDatahub(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &DatahubFilterer{contract: contract}, nil +} + +// bindDatahub binds a generic wrapper to an already deployed contract. +func bindDatahub(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(DatahubABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Datahub *DatahubRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Datahub.Contract.DatahubCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Datahub *DatahubRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Datahub.Contract.DatahubTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Datahub *DatahubRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Datahub.Contract.DatahubTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Datahub *DatahubCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Datahub.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Datahub *DatahubTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Datahub.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Datahub *DatahubTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Datahub.Contract.contract.Transact(opts, method, params...) +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Datahub *DatahubCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Datahub *DatahubSession) DEFAULTADMINROLE() ([32]byte, error) { + return _Datahub.Contract.DEFAULTADMINROLE(&_Datahub.CallOpts) +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Datahub *DatahubCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _Datahub.Contract.DEFAULTADMINROLE(&_Datahub.CallOpts) +} + +// ROLEREPORTER is a free data retrieval call binding the contract method 0x83102c2b. +// +// Solidity: function ROLE_REPORTER() view returns(bytes32) +func (_Datahub *DatahubCaller) ROLEREPORTER(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "ROLE_REPORTER") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// ROLEREPORTER is a free data retrieval call binding the contract method 0x83102c2b. +// +// Solidity: function ROLE_REPORTER() view returns(bytes32) +func (_Datahub *DatahubSession) ROLEREPORTER() ([32]byte, error) { + return _Datahub.Contract.ROLEREPORTER(&_Datahub.CallOpts) +} + +// ROLEREPORTER is a free data retrieval call binding the contract method 0x83102c2b. +// +// Solidity: function ROLE_REPORTER() view returns(bytes32) +func (_Datahub *DatahubCallerSession) ROLEREPORTER() ([32]byte, error) { + return _Datahub.Contract.ROLEREPORTER(&_Datahub.CallOpts) +} + +// FeesCollected is a free data retrieval call binding the contract method 0xf071db5a. +// +// Solidity: function feesCollected() view returns(uint256) +func (_Datahub *DatahubCaller) FeesCollected(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "feesCollected") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// FeesCollected is a free data retrieval call binding the contract method 0xf071db5a. +// +// Solidity: function feesCollected() view returns(uint256) +func (_Datahub *DatahubSession) FeesCollected() (*big.Int, error) { + return _Datahub.Contract.FeesCollected(&_Datahub.CallOpts) +} + +// FeesCollected is a free data retrieval call binding the contract method 0xf071db5a. +// +// Solidity: function feesCollected() view returns(uint256) +func (_Datahub *DatahubCallerSession) FeesCollected() (*big.Int, error) { + return _Datahub.Contract.FeesCollected(&_Datahub.CallOpts) +} + +// FundsBalance is a free data retrieval call binding the contract method 0x9454932c. +// +// Solidity: function fundsBalance() view returns(uint256) +func (_Datahub *DatahubCaller) FundsBalance(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "fundsBalance") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// FundsBalance is a free data retrieval call binding the contract method 0x9454932c. +// +// Solidity: function fundsBalance() view returns(uint256) +func (_Datahub *DatahubSession) FundsBalance() (*big.Int, error) { + return _Datahub.Contract.FundsBalance(&_Datahub.CallOpts) +} + +// FundsBalance is a free data retrieval call binding the contract method 0x9454932c. +// +// Solidity: function fundsBalance() view returns(uint256) +func (_Datahub *DatahubCallerSession) FundsBalance() (*big.Int, error) { + return _Datahub.Contract.FundsBalance(&_Datahub.CallOpts) +} + +// GetActiveBidAt is a free data retrieval call binding the contract method 0x78ba33c6. +// +// Solidity: function getActiveBidAt(address addr, uint256 index) view returns((address,bytes32)) +func (_Datahub *DatahubCaller) GetActiveBidAt(opts *bind.CallOpts, addr common.Address, index *big.Int) (DataHubActiveBid, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getActiveBidAt", addr, index) + + if err != nil { + return *new(DataHubActiveBid), err + } + + out0 := *abi.ConvertType(out[0], new(DataHubActiveBid)).(*DataHubActiveBid) + + return out0, err + +} + +// GetActiveBidAt is a free data retrieval call binding the contract method 0x78ba33c6. +// +// Solidity: function getActiveBidAt(address addr, uint256 index) view returns((address,bytes32)) +func (_Datahub *DatahubSession) GetActiveBidAt(addr common.Address, index *big.Int) (DataHubActiveBid, error) { + return _Datahub.Contract.GetActiveBidAt(&_Datahub.CallOpts, addr, index) +} + +// GetActiveBidAt is a free data retrieval call binding the contract method 0x78ba33c6. +// +// Solidity: function getActiveBidAt(address addr, uint256 index) view returns((address,bytes32)) +func (_Datahub *DatahubCallerSession) GetActiveBidAt(addr common.Address, index *big.Int) (DataHubActiveBid, error) { + return _Datahub.Contract.GetActiveBidAt(&_Datahub.CallOpts, addr, index) +} + +// GetActiveBids is a free data retrieval call binding the contract method 0xfbc4fc44. +// +// Solidity: function getActiveBids(address addr) view returns((address,bytes32)[]) +func (_Datahub *DatahubCaller) GetActiveBids(opts *bind.CallOpts, addr common.Address) ([]DataHubActiveBid, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getActiveBids", addr) + + if err != nil { + return *new([]DataHubActiveBid), err + } + + out0 := *abi.ConvertType(out[0], new([]DataHubActiveBid)).(*[]DataHubActiveBid) + + return out0, err + +} + +// GetActiveBids is a free data retrieval call binding the contract method 0xfbc4fc44. +// +// Solidity: function getActiveBids(address addr) view returns((address,bytes32)[]) +func (_Datahub *DatahubSession) GetActiveBids(addr common.Address) ([]DataHubActiveBid, error) { + return _Datahub.Contract.GetActiveBids(&_Datahub.CallOpts, addr) +} + +// GetActiveBids is a free data retrieval call binding the contract method 0xfbc4fc44. +// +// Solidity: function getActiveBids(address addr) view returns((address,bytes32)[]) +func (_Datahub *DatahubCallerSession) GetActiveBids(addr common.Address) ([]DataHubActiveBid, error) { + return _Datahub.Contract.GetActiveBids(&_Datahub.CallOpts, addr) +} + +// GetActiveBidsByHash is a free data retrieval call binding the contract method 0x2da82643. +// +// Solidity: function getActiveBidsByHash(address addr, bytes32 requestHash) view returns((address,bytes32)) +func (_Datahub *DatahubCaller) GetActiveBidsByHash(opts *bind.CallOpts, addr common.Address, requestHash [32]byte) (DataHubActiveBid, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getActiveBidsByHash", addr, requestHash) + + if err != nil { + return *new(DataHubActiveBid), err + } + + out0 := *abi.ConvertType(out[0], new(DataHubActiveBid)).(*DataHubActiveBid) + + return out0, err + +} + +// GetActiveBidsByHash is a free data retrieval call binding the contract method 0x2da82643. +// +// Solidity: function getActiveBidsByHash(address addr, bytes32 requestHash) view returns((address,bytes32)) +func (_Datahub *DatahubSession) GetActiveBidsByHash(addr common.Address, requestHash [32]byte) (DataHubActiveBid, error) { + return _Datahub.Contract.GetActiveBidsByHash(&_Datahub.CallOpts, addr, requestHash) +} + +// GetActiveBidsByHash is a free data retrieval call binding the contract method 0x2da82643. +// +// Solidity: function getActiveBidsByHash(address addr, bytes32 requestHash) view returns((address,bytes32)) +func (_Datahub *DatahubCallerSession) GetActiveBidsByHash(addr common.Address, requestHash [32]byte) (DataHubActiveBid, error) { + return _Datahub.Contract.GetActiveBidsByHash(&_Datahub.CallOpts, addr, requestHash) +} + +// GetAllSubItems is a free data retrieval call binding the contract method 0x224b6b8c. +// +// Solidity: function getAllSubItems(address addr) view returns((bytes32,bytes32,uint256)[]) +func (_Datahub *DatahubCaller) GetAllSubItems(opts *bind.CallOpts, addr common.Address) ([]DataHubSubItem, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getAllSubItems", addr) + + if err != nil { + return *new([]DataHubSubItem), err + } + + out0 := *abi.ConvertType(out[0], new([]DataHubSubItem)).(*[]DataHubSubItem) + + return out0, err + +} + +// GetAllSubItems is a free data retrieval call binding the contract method 0x224b6b8c. +// +// Solidity: function getAllSubItems(address addr) view returns((bytes32,bytes32,uint256)[]) +func (_Datahub *DatahubSession) GetAllSubItems(addr common.Address) ([]DataHubSubItem, error) { + return _Datahub.Contract.GetAllSubItems(&_Datahub.CallOpts, addr) +} + +// GetAllSubItems is a free data retrieval call binding the contract method 0x224b6b8c. +// +// Solidity: function getAllSubItems(address addr) view returns((bytes32,bytes32,uint256)[]) +func (_Datahub *DatahubCallerSession) GetAllSubItems(addr common.Address) ([]DataHubSubItem, error) { + return _Datahub.Contract.GetAllSubItems(&_Datahub.CallOpts, addr) +} + +// GetAllSubItemsForNameHash is a free data retrieval call binding the contract method 0xb62fe12f. +// +// Solidity: function getAllSubItemsForNameHash(bytes32 nameHash) view returns((bytes32,bytes32,uint256)[]) +func (_Datahub *DatahubCaller) GetAllSubItemsForNameHash(opts *bind.CallOpts, nameHash [32]byte) ([]DataHubSubItem, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getAllSubItemsForNameHash", nameHash) + + if err != nil { + return *new([]DataHubSubItem), err + } + + out0 := *abi.ConvertType(out[0], new([]DataHubSubItem)).(*[]DataHubSubItem) + + return out0, err + +} + +// GetAllSubItemsForNameHash is a free data retrieval call binding the contract method 0xb62fe12f. +// +// Solidity: function getAllSubItemsForNameHash(bytes32 nameHash) view returns((bytes32,bytes32,uint256)[]) +func (_Datahub *DatahubSession) GetAllSubItemsForNameHash(nameHash [32]byte) ([]DataHubSubItem, error) { + return _Datahub.Contract.GetAllSubItemsForNameHash(&_Datahub.CallOpts, nameHash) +} + +// GetAllSubItemsForNameHash is a free data retrieval call binding the contract method 0xb62fe12f. +// +// Solidity: function getAllSubItemsForNameHash(bytes32 nameHash) view returns((bytes32,bytes32,uint256)[]) +func (_Datahub *DatahubCallerSession) GetAllSubItemsForNameHash(nameHash [32]byte) ([]DataHubSubItem, error) { + return _Datahub.Contract.GetAllSubItemsForNameHash(&_Datahub.CallOpts, nameHash) +} + +// GetCategory is a free data retrieval call binding the contract method 0x473b084c. +// +// Solidity: function getCategory(bytes32 category) view returns((uint64[])) +func (_Datahub *DatahubCaller) GetCategory(opts *bind.CallOpts, category [32]byte) (DataHubCategory, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getCategory", category) + + if err != nil { + return *new(DataHubCategory), err + } + + out0 := *abi.ConvertType(out[0], new(DataHubCategory)).(*DataHubCategory) + + return out0, err + +} + +// GetCategory is a free data retrieval call binding the contract method 0x473b084c. +// +// Solidity: function getCategory(bytes32 category) view returns((uint64[])) +func (_Datahub *DatahubSession) GetCategory(category [32]byte) (DataHubCategory, error) { + return _Datahub.Contract.GetCategory(&_Datahub.CallOpts, category) +} + +// GetCategory is a free data retrieval call binding the contract method 0x473b084c. +// +// Solidity: function getCategory(bytes32 category) view returns((uint64[])) +func (_Datahub *DatahubCallerSession) GetCategory(category [32]byte) (DataHubCategory, error) { + return _Datahub.Contract.GetCategory(&_Datahub.CallOpts, category) +} + +// GetFee is a free data retrieval call binding the contract method 0xd250185c. +// +// Solidity: function getFee(uint256 _fee, uint256 amount) pure returns(uint256) +func (_Datahub *DatahubCaller) GetFee(opts *bind.CallOpts, _fee *big.Int, amount *big.Int) (*big.Int, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getFee", _fee, amount) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetFee is a free data retrieval call binding the contract method 0xd250185c. +// +// Solidity: function getFee(uint256 _fee, uint256 amount) pure returns(uint256) +func (_Datahub *DatahubSession) GetFee(_fee *big.Int, amount *big.Int) (*big.Int, error) { + return _Datahub.Contract.GetFee(&_Datahub.CallOpts, _fee, amount) +} + +// GetFee is a free data retrieval call binding the contract method 0xd250185c. +// +// Solidity: function getFee(uint256 _fee, uint256 amount) pure returns(uint256) +func (_Datahub *DatahubCallerSession) GetFee(_fee *big.Int, amount *big.Int) (*big.Int, error) { + return _Datahub.Contract.GetFee(&_Datahub.CallOpts, _fee, amount) +} + +// GetListedSubs is a free data retrieval call binding the contract method 0xcddf64ea. +// +// Solidity: function getListedSubs(address addr) view returns(bytes32[]) +func (_Datahub *DatahubCaller) GetListedSubs(opts *bind.CallOpts, addr common.Address) ([][32]byte, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getListedSubs", addr) + + if err != nil { + return *new([][32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([][32]byte)).(*[][32]byte) + + return out0, err + +} + +// GetListedSubs is a free data retrieval call binding the contract method 0xcddf64ea. +// +// Solidity: function getListedSubs(address addr) view returns(bytes32[]) +func (_Datahub *DatahubSession) GetListedSubs(addr common.Address) ([][32]byte, error) { + return _Datahub.Contract.GetListedSubs(&_Datahub.CallOpts, addr) +} + +// GetListedSubs is a free data retrieval call binding the contract method 0xcddf64ea. +// +// Solidity: function getListedSubs(address addr) view returns(bytes32[]) +func (_Datahub *DatahubCallerSession) GetListedSubs(addr common.Address) ([][32]byte, error) { + return _Datahub.Contract.GetListedSubs(&_Datahub.CallOpts, addr) +} + +// GetNameHashSubItems is a free data retrieval call binding the contract method 0x2c3ca35a. +// +// Solidity: function getNameHashSubItems(bytes32 nameHash) view returns(bytes32[]) +func (_Datahub *DatahubCaller) GetNameHashSubItems(opts *bind.CallOpts, nameHash [32]byte) ([][32]byte, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getNameHashSubItems", nameHash) + + if err != nil { + return *new([][32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([][32]byte)).(*[][32]byte) + + return out0, err + +} + +// GetNameHashSubItems is a free data retrieval call binding the contract method 0x2c3ca35a. +// +// Solidity: function getNameHashSubItems(bytes32 nameHash) view returns(bytes32[]) +func (_Datahub *DatahubSession) GetNameHashSubItems(nameHash [32]byte) ([][32]byte, error) { + return _Datahub.Contract.GetNameHashSubItems(&_Datahub.CallOpts, nameHash) +} + +// GetNameHashSubItems is a free data retrieval call binding the contract method 0x2c3ca35a. +// +// Solidity: function getNameHashSubItems(bytes32 nameHash) view returns(bytes32[]) +func (_Datahub *DatahubCallerSession) GetNameHashSubItems(nameHash [32]byte) ([][32]byte, error) { + return _Datahub.Contract.GetNameHashSubItems(&_Datahub.CallOpts, nameHash) +} + +// GetPortableAddress is a free data retrieval call binding the contract method 0xc3b4dde9. +// +// Solidity: function getPortableAddress(address addr) view returns(address) +func (_Datahub *DatahubCaller) GetPortableAddress(opts *bind.CallOpts, addr common.Address) (common.Address, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getPortableAddress", addr) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetPortableAddress is a free data retrieval call binding the contract method 0xc3b4dde9. +// +// Solidity: function getPortableAddress(address addr) view returns(address) +func (_Datahub *DatahubSession) GetPortableAddress(addr common.Address) (common.Address, error) { + return _Datahub.Contract.GetPortableAddress(&_Datahub.CallOpts, addr) +} + +// GetPortableAddress is a free data retrieval call binding the contract method 0xc3b4dde9. +// +// Solidity: function getPortableAddress(address addr) view returns(address) +func (_Datahub *DatahubCallerSession) GetPortableAddress(addr common.Address) (common.Address, error) { + return _Datahub.Contract.GetPortableAddress(&_Datahub.CallOpts, addr) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Datahub *DatahubCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getRoleAdmin", role) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Datahub *DatahubSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _Datahub.Contract.GetRoleAdmin(&_Datahub.CallOpts, role) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Datahub *DatahubCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _Datahub.Contract.GetRoleAdmin(&_Datahub.CallOpts, role) +} + +// GetSubBy is a free data retrieval call binding the contract method 0x1f9ef490. +// +// Solidity: function getSubBy(bytes32 subHash) view returns((bytes32,bytes32,address,bytes32,uint256,bool,uint256,uint32,uint32,uint32,uint16)) +func (_Datahub *DatahubCaller) GetSubBy(opts *bind.CallOpts, subHash [32]byte) (DataHubSub, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getSubBy", subHash) + + if err != nil { + return *new(DataHubSub), err + } + + out0 := *abi.ConvertType(out[0], new(DataHubSub)).(*DataHubSub) + + return out0, err + +} + +// GetSubBy is a free data retrieval call binding the contract method 0x1f9ef490. +// +// Solidity: function getSubBy(bytes32 subHash) view returns((bytes32,bytes32,address,bytes32,uint256,bool,uint256,uint32,uint32,uint32,uint16)) +func (_Datahub *DatahubSession) GetSubBy(subHash [32]byte) (DataHubSub, error) { + return _Datahub.Contract.GetSubBy(&_Datahub.CallOpts, subHash) +} + +// GetSubBy is a free data retrieval call binding the contract method 0x1f9ef490. +// +// Solidity: function getSubBy(bytes32 subHash) view returns((bytes32,bytes32,address,bytes32,uint256,bool,uint256,uint32,uint32,uint32,uint16)) +func (_Datahub *DatahubCallerSession) GetSubBy(subHash [32]byte) (DataHubSub, error) { + return _Datahub.Contract.GetSubBy(&_Datahub.CallOpts, subHash) +} + +// GetSubByIndex is a free data retrieval call binding the contract method 0xeed5b6e5. +// +// Solidity: function getSubByIndex(uint256 index) view returns((bytes32,bytes32,address,bytes32,uint256,bool,uint256,uint32,uint32,uint32,uint16)) +func (_Datahub *DatahubCaller) GetSubByIndex(opts *bind.CallOpts, index *big.Int) (DataHubSub, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getSubByIndex", index) + + if err != nil { + return *new(DataHubSub), err + } + + out0 := *abi.ConvertType(out[0], new(DataHubSub)).(*DataHubSub) + + return out0, err + +} + +// GetSubByIndex is a free data retrieval call binding the contract method 0xeed5b6e5. +// +// Solidity: function getSubByIndex(uint256 index) view returns((bytes32,bytes32,address,bytes32,uint256,bool,uint256,uint32,uint32,uint32,uint16)) +func (_Datahub *DatahubSession) GetSubByIndex(index *big.Int) (DataHubSub, error) { + return _Datahub.Contract.GetSubByIndex(&_Datahub.CallOpts, index) +} + +// GetSubByIndex is a free data retrieval call binding the contract method 0xeed5b6e5. +// +// Solidity: function getSubByIndex(uint256 index) view returns((bytes32,bytes32,address,bytes32,uint256,bool,uint256,uint32,uint32,uint32,uint16)) +func (_Datahub *DatahubCallerSession) GetSubByIndex(index *big.Int) (DataHubSub, error) { + return _Datahub.Contract.GetSubByIndex(&_Datahub.CallOpts, index) +} + +// GetSubInfoBalance is a free data retrieval call binding the contract method 0x254e287b. +// +// Solidity: function getSubInfoBalance(bytes32 subHash, address forAddress) view returns(uint256) +func (_Datahub *DatahubCaller) GetSubInfoBalance(opts *bind.CallOpts, subHash [32]byte, forAddress common.Address) (*big.Int, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getSubInfoBalance", subHash, forAddress) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetSubInfoBalance is a free data retrieval call binding the contract method 0x254e287b. +// +// Solidity: function getSubInfoBalance(bytes32 subHash, address forAddress) view returns(uint256) +func (_Datahub *DatahubSession) GetSubInfoBalance(subHash [32]byte, forAddress common.Address) (*big.Int, error) { + return _Datahub.Contract.GetSubInfoBalance(&_Datahub.CallOpts, subHash, forAddress) +} + +// GetSubInfoBalance is a free data retrieval call binding the contract method 0x254e287b. +// +// Solidity: function getSubInfoBalance(bytes32 subHash, address forAddress) view returns(uint256) +func (_Datahub *DatahubCallerSession) GetSubInfoBalance(subHash [32]byte, forAddress common.Address) (*big.Int, error) { + return _Datahub.Contract.GetSubInfoBalance(&_Datahub.CallOpts, subHash, forAddress) +} + +// GetSubItemAt is a free data retrieval call binding the contract method 0x80dd0d8e. +// +// Solidity: function getSubItemAt(address addr, uint256 index) view returns((bytes32,bytes32,uint256)) +func (_Datahub *DatahubCaller) GetSubItemAt(opts *bind.CallOpts, addr common.Address, index *big.Int) (DataHubSubItem, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getSubItemAt", addr, index) + + if err != nil { + return *new(DataHubSubItem), err + } + + out0 := *abi.ConvertType(out[0], new(DataHubSubItem)).(*DataHubSubItem) + + return out0, err + +} + +// GetSubItemAt is a free data retrieval call binding the contract method 0x80dd0d8e. +// +// Solidity: function getSubItemAt(address addr, uint256 index) view returns((bytes32,bytes32,uint256)) +func (_Datahub *DatahubSession) GetSubItemAt(addr common.Address, index *big.Int) (DataHubSubItem, error) { + return _Datahub.Contract.GetSubItemAt(&_Datahub.CallOpts, addr, index) +} + +// GetSubItemAt is a free data retrieval call binding the contract method 0x80dd0d8e. +// +// Solidity: function getSubItemAt(address addr, uint256 index) view returns((bytes32,bytes32,uint256)) +func (_Datahub *DatahubCallerSession) GetSubItemAt(addr common.Address, index *big.Int) (DataHubSubItem, error) { + return _Datahub.Contract.GetSubItemAt(&_Datahub.CallOpts, addr, index) +} + +// GetSubItems is a free data retrieval call binding the contract method 0xd3fbc74c. +// +// Solidity: function getSubItems(address addr, uint256 start, uint256 length) view returns((bytes32,bytes32,uint256)[] items, uint256 last) +func (_Datahub *DatahubCaller) GetSubItems(opts *bind.CallOpts, addr common.Address, start *big.Int, length *big.Int) (struct { + Items []DataHubSubItem + Last *big.Int +}, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getSubItems", addr, start, length) + + outstruct := new(struct { + Items []DataHubSubItem + Last *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.Items = *abi.ConvertType(out[0], new([]DataHubSubItem)).(*[]DataHubSubItem) + outstruct.Last = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// GetSubItems is a free data retrieval call binding the contract method 0xd3fbc74c. +// +// Solidity: function getSubItems(address addr, uint256 start, uint256 length) view returns((bytes32,bytes32,uint256)[] items, uint256 last) +func (_Datahub *DatahubSession) GetSubItems(addr common.Address, start *big.Int, length *big.Int) (struct { + Items []DataHubSubItem + Last *big.Int +}, error) { + return _Datahub.Contract.GetSubItems(&_Datahub.CallOpts, addr, start, length) +} + +// GetSubItems is a free data retrieval call binding the contract method 0xd3fbc74c. +// +// Solidity: function getSubItems(address addr, uint256 start, uint256 length) view returns((bytes32,bytes32,uint256)[] items, uint256 last) +func (_Datahub *DatahubCallerSession) GetSubItems(addr common.Address, start *big.Int, length *big.Int) (struct { + Items []DataHubSubItem + Last *big.Int +}, error) { + return _Datahub.Contract.GetSubItems(&_Datahub.CallOpts, addr, start, length) +} + +// GetSubRequestAt is a free data retrieval call binding the contract method 0x84053229. +// +// Solidity: function getSubRequestAt(address addr, uint256 index) view returns((bytes32,address,bytes32,bytes32)) +func (_Datahub *DatahubCaller) GetSubRequestAt(opts *bind.CallOpts, addr common.Address, index *big.Int) (DataHubSubRequest, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getSubRequestAt", addr, index) + + if err != nil { + return *new(DataHubSubRequest), err + } + + out0 := *abi.ConvertType(out[0], new(DataHubSubRequest)).(*DataHubSubRequest) + + return out0, err + +} + +// GetSubRequestAt is a free data retrieval call binding the contract method 0x84053229. +// +// Solidity: function getSubRequestAt(address addr, uint256 index) view returns((bytes32,address,bytes32,bytes32)) +func (_Datahub *DatahubSession) GetSubRequestAt(addr common.Address, index *big.Int) (DataHubSubRequest, error) { + return _Datahub.Contract.GetSubRequestAt(&_Datahub.CallOpts, addr, index) +} + +// GetSubRequestAt is a free data retrieval call binding the contract method 0x84053229. +// +// Solidity: function getSubRequestAt(address addr, uint256 index) view returns((bytes32,address,bytes32,bytes32)) +func (_Datahub *DatahubCallerSession) GetSubRequestAt(addr common.Address, index *big.Int) (DataHubSubRequest, error) { + return _Datahub.Contract.GetSubRequestAt(&_Datahub.CallOpts, addr, index) +} + +// GetSubRequestByHash is a free data retrieval call binding the contract method 0x9bde82dc. +// +// Solidity: function getSubRequestByHash(address addr, bytes32 requestHash) view returns((bytes32,address,bytes32,bytes32)) +func (_Datahub *DatahubCaller) GetSubRequestByHash(opts *bind.CallOpts, addr common.Address, requestHash [32]byte) (DataHubSubRequest, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getSubRequestByHash", addr, requestHash) + + if err != nil { + return *new(DataHubSubRequest), err + } + + out0 := *abi.ConvertType(out[0], new(DataHubSubRequest)).(*DataHubSubRequest) + + return out0, err + +} + +// GetSubRequestByHash is a free data retrieval call binding the contract method 0x9bde82dc. +// +// Solidity: function getSubRequestByHash(address addr, bytes32 requestHash) view returns((bytes32,address,bytes32,bytes32)) +func (_Datahub *DatahubSession) GetSubRequestByHash(addr common.Address, requestHash [32]byte) (DataHubSubRequest, error) { + return _Datahub.Contract.GetSubRequestByHash(&_Datahub.CallOpts, addr, requestHash) +} + +// GetSubRequestByHash is a free data retrieval call binding the contract method 0x9bde82dc. +// +// Solidity: function getSubRequestByHash(address addr, bytes32 requestHash) view returns((bytes32,address,bytes32,bytes32)) +func (_Datahub *DatahubCallerSession) GetSubRequestByHash(addr common.Address, requestHash [32]byte) (DataHubSubRequest, error) { + return _Datahub.Contract.GetSubRequestByHash(&_Datahub.CallOpts, addr, requestHash) +} + +// GetSubRequests is a free data retrieval call binding the contract method 0x92b58bc2. +// +// Solidity: function getSubRequests(address addr) view returns((bytes32,address,bytes32,bytes32)[]) +func (_Datahub *DatahubCaller) GetSubRequests(opts *bind.CallOpts, addr common.Address) ([]DataHubSubRequest, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getSubRequests", addr) + + if err != nil { + return *new([]DataHubSubRequest), err + } + + out0 := *abi.ConvertType(out[0], new([]DataHubSubRequest)).(*[]DataHubSubRequest) + + return out0, err + +} + +// GetSubRequests is a free data retrieval call binding the contract method 0x92b58bc2. +// +// Solidity: function getSubRequests(address addr) view returns((bytes32,address,bytes32,bytes32)[]) +func (_Datahub *DatahubSession) GetSubRequests(addr common.Address) ([]DataHubSubRequest, error) { + return _Datahub.Contract.GetSubRequests(&_Datahub.CallOpts, addr) +} + +// GetSubRequests is a free data retrieval call binding the contract method 0x92b58bc2. +// +// Solidity: function getSubRequests(address addr) view returns((bytes32,address,bytes32,bytes32)[]) +func (_Datahub *DatahubCallerSession) GetSubRequests(addr common.Address) ([]DataHubSubRequest, error) { + return _Datahub.Contract.GetSubRequests(&_Datahub.CallOpts, addr) +} + +// GetSubSubscribers is a free data retrieval call binding the contract method 0x7de2e5e8. +// +// Solidity: function getSubSubscribers(bytes32 subHash) view returns(address[]) +func (_Datahub *DatahubCaller) GetSubSubscribers(opts *bind.CallOpts, subHash [32]byte) ([]common.Address, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getSubSubscribers", subHash) + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// GetSubSubscribers is a free data retrieval call binding the contract method 0x7de2e5e8. +// +// Solidity: function getSubSubscribers(bytes32 subHash) view returns(address[]) +func (_Datahub *DatahubSession) GetSubSubscribers(subHash [32]byte) ([]common.Address, error) { + return _Datahub.Contract.GetSubSubscribers(&_Datahub.CallOpts, subHash) +} + +// GetSubSubscribers is a free data retrieval call binding the contract method 0x7de2e5e8. +// +// Solidity: function getSubSubscribers(bytes32 subHash) view returns(address[]) +func (_Datahub *DatahubCallerSession) GetSubSubscribers(subHash [32]byte) ([]common.Address, error) { + return _Datahub.Contract.GetSubSubscribers(&_Datahub.CallOpts, subHash) +} + +// GetSubs is a free data retrieval call binding the contract method 0xb8fb1bac. +// +// Solidity: function getSubs() view returns((bytes32,bytes32,address,bytes32,uint256,bool,uint256,uint32,uint32,uint32,uint16)[]) +func (_Datahub *DatahubCaller) GetSubs(opts *bind.CallOpts) ([]DataHubSub, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getSubs") + + if err != nil { + return *new([]DataHubSub), err + } + + out0 := *abi.ConvertType(out[0], new([]DataHubSub)).(*[]DataHubSub) + + return out0, err + +} + +// GetSubs is a free data retrieval call binding the contract method 0xb8fb1bac. +// +// Solidity: function getSubs() view returns((bytes32,bytes32,address,bytes32,uint256,bool,uint256,uint32,uint32,uint32,uint16)[]) +func (_Datahub *DatahubSession) GetSubs() ([]DataHubSub, error) { + return _Datahub.Contract.GetSubs(&_Datahub.CallOpts) +} + +// GetSubs is a free data retrieval call binding the contract method 0xb8fb1bac. +// +// Solidity: function getSubs() view returns((bytes32,bytes32,address,bytes32,uint256,bool,uint256,uint32,uint32,uint32,uint16)[]) +func (_Datahub *DatahubCallerSession) GetSubs() ([]DataHubSub, error) { + return _Datahub.Contract.GetSubs(&_Datahub.CallOpts) +} + +// GetUserStats is a free data retrieval call binding the contract method 0x4e43603a. +// +// Solidity: function getUserStats(address addr) view returns(uint256 numSubRequests, uint256 numSubItems, uint256 numActiveBids, uint256 numListedSubs) +func (_Datahub *DatahubCaller) GetUserStats(opts *bind.CallOpts, addr common.Address) (struct { + NumSubRequests *big.Int + NumSubItems *big.Int + NumActiveBids *big.Int + NumListedSubs *big.Int +}, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "getUserStats", addr) + + outstruct := new(struct { + NumSubRequests *big.Int + NumSubItems *big.Int + NumActiveBids *big.Int + NumListedSubs *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.NumSubRequests = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.NumSubItems = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.NumActiveBids = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + outstruct.NumListedSubs = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// GetUserStats is a free data retrieval call binding the contract method 0x4e43603a. +// +// Solidity: function getUserStats(address addr) view returns(uint256 numSubRequests, uint256 numSubItems, uint256 numActiveBids, uint256 numListedSubs) +func (_Datahub *DatahubSession) GetUserStats(addr common.Address) (struct { + NumSubRequests *big.Int + NumSubItems *big.Int + NumActiveBids *big.Int + NumListedSubs *big.Int +}, error) { + return _Datahub.Contract.GetUserStats(&_Datahub.CallOpts, addr) +} + +// GetUserStats is a free data retrieval call binding the contract method 0x4e43603a. +// +// Solidity: function getUserStats(address addr) view returns(uint256 numSubRequests, uint256 numSubItems, uint256 numActiveBids, uint256 numListedSubs) +func (_Datahub *DatahubCallerSession) GetUserStats(addr common.Address) (struct { + NumSubRequests *big.Int + NumSubItems *big.Int + NumActiveBids *big.Int + NumListedSubs *big.Int +}, error) { + return _Datahub.Contract.GetUserStats(&_Datahub.CallOpts, addr) +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Datahub *DatahubCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "hasRole", role, account) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Datahub *DatahubSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _Datahub.Contract.HasRole(&_Datahub.CallOpts, role, account) +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Datahub *DatahubCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _Datahub.Contract.HasRole(&_Datahub.CallOpts, role, account) +} + +// InEscrow is a free data retrieval call binding the contract method 0xb7391341. +// +// Solidity: function inEscrow() view returns(uint256) +func (_Datahub *DatahubCaller) InEscrow(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "inEscrow") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// InEscrow is a free data retrieval call binding the contract method 0xb7391341. +// +// Solidity: function inEscrow() view returns(uint256) +func (_Datahub *DatahubSession) InEscrow() (*big.Int, error) { + return _Datahub.Contract.InEscrow(&_Datahub.CallOpts) +} + +// InEscrow is a free data retrieval call binding the contract method 0xb7391341. +// +// Solidity: function inEscrow() view returns(uint256) +func (_Datahub *DatahubCallerSession) InEscrow() (*big.Int, error) { + return _Datahub.Contract.InEscrow(&_Datahub.CallOpts) +} + +// MarketFee is a free data retrieval call binding the contract method 0x0ccf2156. +// +// Solidity: function marketFee() view returns(uint256) +func (_Datahub *DatahubCaller) MarketFee(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "marketFee") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MarketFee is a free data retrieval call binding the contract method 0x0ccf2156. +// +// Solidity: function marketFee() view returns(uint256) +func (_Datahub *DatahubSession) MarketFee() (*big.Int, error) { + return _Datahub.Contract.MarketFee(&_Datahub.CallOpts) +} + +// MarketFee is a free data retrieval call binding the contract method 0x0ccf2156. +// +// Solidity: function marketFee() view returns(uint256) +func (_Datahub *DatahubCallerSession) MarketFee() (*big.Int, error) { + return _Datahub.Contract.MarketFee(&_Datahub.CallOpts) +} + +// MinListingFee is a free data retrieval call binding the contract method 0x703a54b5. +// +// Solidity: function minListingFee() view returns(uint256) +func (_Datahub *DatahubCaller) MinListingFee(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "minListingFee") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MinListingFee is a free data retrieval call binding the contract method 0x703a54b5. +// +// Solidity: function minListingFee() view returns(uint256) +func (_Datahub *DatahubSession) MinListingFee() (*big.Int, error) { + return _Datahub.Contract.MinListingFee(&_Datahub.CallOpts) +} + +// MinListingFee is a free data retrieval call binding the contract method 0x703a54b5. +// +// Solidity: function minListingFee() view returns(uint256) +func (_Datahub *DatahubCallerSession) MinListingFee() (*big.Int, error) { + return _Datahub.Contract.MinListingFee(&_Datahub.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Datahub *DatahubCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Datahub *DatahubSession) Owner() (common.Address, error) { + return _Datahub.Contract.Owner(&_Datahub.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Datahub *DatahubCallerSession) Owner() (common.Address, error) { + return _Datahub.Contract.Owner(&_Datahub.CallOpts) +} + +// SubscriptionIds is a free data retrieval call binding the contract method 0x0e499994. +// +// Solidity: function subscriptionIds(bytes32 ) view returns(uint256) +func (_Datahub *DatahubCaller) SubscriptionIds(opts *bind.CallOpts, arg0 [32]byte) (*big.Int, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "subscriptionIds", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// SubscriptionIds is a free data retrieval call binding the contract method 0x0e499994. +// +// Solidity: function subscriptionIds(bytes32 ) view returns(uint256) +func (_Datahub *DatahubSession) SubscriptionIds(arg0 [32]byte) (*big.Int, error) { + return _Datahub.Contract.SubscriptionIds(&_Datahub.CallOpts, arg0) +} + +// SubscriptionIds is a free data retrieval call binding the contract method 0x0e499994. +// +// Solidity: function subscriptionIds(bytes32 ) view returns(uint256) +func (_Datahub *DatahubCallerSession) SubscriptionIds(arg0 [32]byte) (*big.Int, error) { + return _Datahub.Contract.SubscriptionIds(&_Datahub.CallOpts, arg0) +} + +// Subscriptions is a free data retrieval call binding the contract method 0x2d5bbf60. +// +// Solidity: function subscriptions(uint256 ) view returns(bytes32 subHash, bytes32 fdpSellerNameHash, address seller, bytes32 swarmLocation, uint256 price, bool active, uint256 earned, uint32 bids, uint32 sells, uint32 reports, uint16 daysValid) +func (_Datahub *DatahubCaller) Subscriptions(opts *bind.CallOpts, arg0 *big.Int) (struct { + SubHash [32]byte + FdpSellerNameHash [32]byte + Seller common.Address + SwarmLocation [32]byte + Price *big.Int + Active bool + Earned *big.Int + Bids uint32 + Sells uint32 + Reports uint32 + DaysValid uint16 +}, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "subscriptions", arg0) + + outstruct := new(struct { + SubHash [32]byte + FdpSellerNameHash [32]byte + Seller common.Address + SwarmLocation [32]byte + Price *big.Int + Active bool + Earned *big.Int + Bids uint32 + Sells uint32 + Reports uint32 + DaysValid uint16 + }) + if err != nil { + return *outstruct, err + } + + outstruct.SubHash = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + outstruct.FdpSellerNameHash = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) + outstruct.Seller = *abi.ConvertType(out[2], new(common.Address)).(*common.Address) + outstruct.SwarmLocation = *abi.ConvertType(out[3], new([32]byte)).(*[32]byte) + outstruct.Price = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + outstruct.Active = *abi.ConvertType(out[5], new(bool)).(*bool) + outstruct.Earned = *abi.ConvertType(out[6], new(*big.Int)).(**big.Int) + outstruct.Bids = *abi.ConvertType(out[7], new(uint32)).(*uint32) + outstruct.Sells = *abi.ConvertType(out[8], new(uint32)).(*uint32) + outstruct.Reports = *abi.ConvertType(out[9], new(uint32)).(*uint32) + outstruct.DaysValid = *abi.ConvertType(out[10], new(uint16)).(*uint16) + + return *outstruct, err + +} + +// Subscriptions is a free data retrieval call binding the contract method 0x2d5bbf60. +// +// Solidity: function subscriptions(uint256 ) view returns(bytes32 subHash, bytes32 fdpSellerNameHash, address seller, bytes32 swarmLocation, uint256 price, bool active, uint256 earned, uint32 bids, uint32 sells, uint32 reports, uint16 daysValid) +func (_Datahub *DatahubSession) Subscriptions(arg0 *big.Int) (struct { + SubHash [32]byte + FdpSellerNameHash [32]byte + Seller common.Address + SwarmLocation [32]byte + Price *big.Int + Active bool + Earned *big.Int + Bids uint32 + Sells uint32 + Reports uint32 + DaysValid uint16 +}, error) { + return _Datahub.Contract.Subscriptions(&_Datahub.CallOpts, arg0) +} + +// Subscriptions is a free data retrieval call binding the contract method 0x2d5bbf60. +// +// Solidity: function subscriptions(uint256 ) view returns(bytes32 subHash, bytes32 fdpSellerNameHash, address seller, bytes32 swarmLocation, uint256 price, bool active, uint256 earned, uint32 bids, uint32 sells, uint32 reports, uint16 daysValid) +func (_Datahub *DatahubCallerSession) Subscriptions(arg0 *big.Int) (struct { + SubHash [32]byte + FdpSellerNameHash [32]byte + Seller common.Address + SwarmLocation [32]byte + Price *big.Int + Active bool + Earned *big.Int + Bids uint32 + Sells uint32 + Reports uint32 + DaysValid uint16 +}, error) { + return _Datahub.Contract.Subscriptions(&_Datahub.CallOpts, arg0) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Datahub *DatahubCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _Datahub.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Datahub *DatahubSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Datahub.Contract.SupportsInterface(&_Datahub.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Datahub *DatahubCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Datahub.Contract.SupportsInterface(&_Datahub.CallOpts, interfaceId) +} + +// BidSub is a paid mutator transaction binding the contract method 0xe91dbcb0. +// +// Solidity: function bidSub(bytes32 subHash, bytes32 fdpBuyerNameHash) payable returns() +func (_Datahub *DatahubTransactor) BidSub(opts *bind.TransactOpts, subHash [32]byte, fdpBuyerNameHash [32]byte) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "bidSub", subHash, fdpBuyerNameHash) +} + +// BidSub is a paid mutator transaction binding the contract method 0xe91dbcb0. +// +// Solidity: function bidSub(bytes32 subHash, bytes32 fdpBuyerNameHash) payable returns() +func (_Datahub *DatahubSession) BidSub(subHash [32]byte, fdpBuyerNameHash [32]byte) (*types.Transaction, error) { + return _Datahub.Contract.BidSub(&_Datahub.TransactOpts, subHash, fdpBuyerNameHash) +} + +// BidSub is a paid mutator transaction binding the contract method 0xe91dbcb0. +// +// Solidity: function bidSub(bytes32 subHash, bytes32 fdpBuyerNameHash) payable returns() +func (_Datahub *DatahubTransactorSession) BidSub(subHash [32]byte, fdpBuyerNameHash [32]byte) (*types.Transaction, error) { + return _Datahub.Contract.BidSub(&_Datahub.TransactOpts, subHash, fdpBuyerNameHash) +} + +// EnableSub is a paid mutator transaction binding the contract method 0x88ac2917. +// +// Solidity: function enableSub(bytes32 subHash, bool active) returns() +func (_Datahub *DatahubTransactor) EnableSub(opts *bind.TransactOpts, subHash [32]byte, active bool) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "enableSub", subHash, active) +} + +// EnableSub is a paid mutator transaction binding the contract method 0x88ac2917. +// +// Solidity: function enableSub(bytes32 subHash, bool active) returns() +func (_Datahub *DatahubSession) EnableSub(subHash [32]byte, active bool) (*types.Transaction, error) { + return _Datahub.Contract.EnableSub(&_Datahub.TransactOpts, subHash, active) +} + +// EnableSub is a paid mutator transaction binding the contract method 0x88ac2917. +// +// Solidity: function enableSub(bytes32 subHash, bool active) returns() +func (_Datahub *DatahubTransactorSession) EnableSub(subHash [32]byte, active bool) (*types.Transaction, error) { + return _Datahub.Contract.EnableSub(&_Datahub.TransactOpts, subHash, active) +} + +// FundsTransfer is a paid mutator transaction binding the contract method 0x567556a4. +// +// Solidity: function fundsTransfer() payable returns() +func (_Datahub *DatahubTransactor) FundsTransfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "fundsTransfer") +} + +// FundsTransfer is a paid mutator transaction binding the contract method 0x567556a4. +// +// Solidity: function fundsTransfer() payable returns() +func (_Datahub *DatahubSession) FundsTransfer() (*types.Transaction, error) { + return _Datahub.Contract.FundsTransfer(&_Datahub.TransactOpts) +} + +// FundsTransfer is a paid mutator transaction binding the contract method 0x567556a4. +// +// Solidity: function fundsTransfer() payable returns() +func (_Datahub *DatahubTransactorSession) FundsTransfer() (*types.Transaction, error) { + return _Datahub.Contract.FundsTransfer(&_Datahub.TransactOpts) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Datahub *DatahubTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "grantRole", role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Datahub *DatahubSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Datahub.Contract.GrantRole(&_Datahub.TransactOpts, role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Datahub *DatahubTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Datahub.Contract.GrantRole(&_Datahub.TransactOpts, role, account) +} + +// ListSub is a paid mutator transaction binding the contract method 0x202cff8a. +// +// Solidity: function listSub(bytes32 fdpSellerNameHash, bytes32 dataSwarmLocation, uint256 price, bytes32 category, address podAddress, uint16 daysValid) payable returns() +func (_Datahub *DatahubTransactor) ListSub(opts *bind.TransactOpts, fdpSellerNameHash [32]byte, dataSwarmLocation [32]byte, price *big.Int, category [32]byte, podAddress common.Address, daysValid uint16) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "listSub", fdpSellerNameHash, dataSwarmLocation, price, category, podAddress, daysValid) +} + +// ListSub is a paid mutator transaction binding the contract method 0x202cff8a. +// +// Solidity: function listSub(bytes32 fdpSellerNameHash, bytes32 dataSwarmLocation, uint256 price, bytes32 category, address podAddress, uint16 daysValid) payable returns() +func (_Datahub *DatahubSession) ListSub(fdpSellerNameHash [32]byte, dataSwarmLocation [32]byte, price *big.Int, category [32]byte, podAddress common.Address, daysValid uint16) (*types.Transaction, error) { + return _Datahub.Contract.ListSub(&_Datahub.TransactOpts, fdpSellerNameHash, dataSwarmLocation, price, category, podAddress, daysValid) +} + +// ListSub is a paid mutator transaction binding the contract method 0x202cff8a. +// +// Solidity: function listSub(bytes32 fdpSellerNameHash, bytes32 dataSwarmLocation, uint256 price, bytes32 category, address podAddress, uint16 daysValid) payable returns() +func (_Datahub *DatahubTransactorSession) ListSub(fdpSellerNameHash [32]byte, dataSwarmLocation [32]byte, price *big.Int, category [32]byte, podAddress common.Address, daysValid uint16) (*types.Transaction, error) { + return _Datahub.Contract.ListSub(&_Datahub.TransactOpts, fdpSellerNameHash, dataSwarmLocation, price, category, podAddress, daysValid) +} + +// Release is a paid mutator transaction binding the contract method 0x0357371d. +// +// Solidity: function release(address token, uint256 amount) returns() +func (_Datahub *DatahubTransactor) Release(opts *bind.TransactOpts, token common.Address, amount *big.Int) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "release", token, amount) +} + +// Release is a paid mutator transaction binding the contract method 0x0357371d. +// +// Solidity: function release(address token, uint256 amount) returns() +func (_Datahub *DatahubSession) Release(token common.Address, amount *big.Int) (*types.Transaction, error) { + return _Datahub.Contract.Release(&_Datahub.TransactOpts, token, amount) +} + +// Release is a paid mutator transaction binding the contract method 0x0357371d. +// +// Solidity: function release(address token, uint256 amount) returns() +func (_Datahub *DatahubTransactorSession) Release(token common.Address, amount *big.Int) (*types.Transaction, error) { + return _Datahub.Contract.Release(&_Datahub.TransactOpts, token, amount) +} + +// RemoveUserActiveBid is a paid mutator transaction binding the contract method 0x0260f912. +// +// Solidity: function removeUserActiveBid(bytes32 requestHash) returns() +func (_Datahub *DatahubTransactor) RemoveUserActiveBid(opts *bind.TransactOpts, requestHash [32]byte) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "removeUserActiveBid", requestHash) +} + +// RemoveUserActiveBid is a paid mutator transaction binding the contract method 0x0260f912. +// +// Solidity: function removeUserActiveBid(bytes32 requestHash) returns() +func (_Datahub *DatahubSession) RemoveUserActiveBid(requestHash [32]byte) (*types.Transaction, error) { + return _Datahub.Contract.RemoveUserActiveBid(&_Datahub.TransactOpts, requestHash) +} + +// RemoveUserActiveBid is a paid mutator transaction binding the contract method 0x0260f912. +// +// Solidity: function removeUserActiveBid(bytes32 requestHash) returns() +func (_Datahub *DatahubTransactorSession) RemoveUserActiveBid(requestHash [32]byte) (*types.Transaction, error) { + return _Datahub.Contract.RemoveUserActiveBid(&_Datahub.TransactOpts, requestHash) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Datahub *DatahubTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Datahub *DatahubSession) RenounceOwnership() (*types.Transaction, error) { + return _Datahub.Contract.RenounceOwnership(&_Datahub.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Datahub *DatahubTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _Datahub.Contract.RenounceOwnership(&_Datahub.TransactOpts) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address account) returns() +func (_Datahub *DatahubTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "renounceRole", role, account) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address account) returns() +func (_Datahub *DatahubSession) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Datahub.Contract.RenounceRole(&_Datahub.TransactOpts, role, account) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address account) returns() +func (_Datahub *DatahubTransactorSession) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Datahub.Contract.RenounceRole(&_Datahub.TransactOpts, role, account) +} + +// ReportSub is a paid mutator transaction binding the contract method 0xd76ac1d1. +// +// Solidity: function reportSub(bytes32 subHash) returns() +func (_Datahub *DatahubTransactor) ReportSub(opts *bind.TransactOpts, subHash [32]byte) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "reportSub", subHash) +} + +// ReportSub is a paid mutator transaction binding the contract method 0xd76ac1d1. +// +// Solidity: function reportSub(bytes32 subHash) returns() +func (_Datahub *DatahubSession) ReportSub(subHash [32]byte) (*types.Transaction, error) { + return _Datahub.Contract.ReportSub(&_Datahub.TransactOpts, subHash) +} + +// ReportSub is a paid mutator transaction binding the contract method 0xd76ac1d1. +// +// Solidity: function reportSub(bytes32 subHash) returns() +func (_Datahub *DatahubTransactorSession) ReportSub(subHash [32]byte) (*types.Transaction, error) { + return _Datahub.Contract.ReportSub(&_Datahub.TransactOpts, subHash) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Datahub *DatahubTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "revokeRole", role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Datahub *DatahubSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Datahub.Contract.RevokeRole(&_Datahub.TransactOpts, role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Datahub *DatahubTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Datahub.Contract.RevokeRole(&_Datahub.TransactOpts, role, account) +} + +// SellSub is a paid mutator transaction binding the contract method 0x3ca684e3. +// +// Solidity: function sellSub(bytes32 requestHash, bytes32 encryptedKeyLocation) payable returns() +func (_Datahub *DatahubTransactor) SellSub(opts *bind.TransactOpts, requestHash [32]byte, encryptedKeyLocation [32]byte) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "sellSub", requestHash, encryptedKeyLocation) +} + +// SellSub is a paid mutator transaction binding the contract method 0x3ca684e3. +// +// Solidity: function sellSub(bytes32 requestHash, bytes32 encryptedKeyLocation) payable returns() +func (_Datahub *DatahubSession) SellSub(requestHash [32]byte, encryptedKeyLocation [32]byte) (*types.Transaction, error) { + return _Datahub.Contract.SellSub(&_Datahub.TransactOpts, requestHash, encryptedKeyLocation) +} + +// SellSub is a paid mutator transaction binding the contract method 0x3ca684e3. +// +// Solidity: function sellSub(bytes32 requestHash, bytes32 encryptedKeyLocation) payable returns() +func (_Datahub *DatahubTransactorSession) SellSub(requestHash [32]byte, encryptedKeyLocation [32]byte) (*types.Transaction, error) { + return _Datahub.Contract.SellSub(&_Datahub.TransactOpts, requestHash, encryptedKeyLocation) +} + +// SetFee is a paid mutator transaction binding the contract method 0x69fe0e2d. +// +// Solidity: function setFee(uint256 newFee) returns() +func (_Datahub *DatahubTransactor) SetFee(opts *bind.TransactOpts, newFee *big.Int) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "setFee", newFee) +} + +// SetFee is a paid mutator transaction binding the contract method 0x69fe0e2d. +// +// Solidity: function setFee(uint256 newFee) returns() +func (_Datahub *DatahubSession) SetFee(newFee *big.Int) (*types.Transaction, error) { + return _Datahub.Contract.SetFee(&_Datahub.TransactOpts, newFee) +} + +// SetFee is a paid mutator transaction binding the contract method 0x69fe0e2d. +// +// Solidity: function setFee(uint256 newFee) returns() +func (_Datahub *DatahubTransactorSession) SetFee(newFee *big.Int) (*types.Transaction, error) { + return _Datahub.Contract.SetFee(&_Datahub.TransactOpts, newFee) +} + +// SetListingFee is a paid mutator transaction binding the contract method 0x131dbd09. +// +// Solidity: function setListingFee(uint256 newListingFee) returns() +func (_Datahub *DatahubTransactor) SetListingFee(opts *bind.TransactOpts, newListingFee *big.Int) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "setListingFee", newListingFee) +} + +// SetListingFee is a paid mutator transaction binding the contract method 0x131dbd09. +// +// Solidity: function setListingFee(uint256 newListingFee) returns() +func (_Datahub *DatahubSession) SetListingFee(newListingFee *big.Int) (*types.Transaction, error) { + return _Datahub.Contract.SetListingFee(&_Datahub.TransactOpts, newListingFee) +} + +// SetListingFee is a paid mutator transaction binding the contract method 0x131dbd09. +// +// Solidity: function setListingFee(uint256 newListingFee) returns() +func (_Datahub *DatahubTransactorSession) SetListingFee(newListingFee *big.Int) (*types.Transaction, error) { + return _Datahub.Contract.SetListingFee(&_Datahub.TransactOpts, newListingFee) +} + +// SetPortableAddress is a paid mutator transaction binding the contract method 0xc6d05aee. +// +// Solidity: function setPortableAddress(address addr) returns() +func (_Datahub *DatahubTransactor) SetPortableAddress(opts *bind.TransactOpts, addr common.Address) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "setPortableAddress", addr) +} + +// SetPortableAddress is a paid mutator transaction binding the contract method 0xc6d05aee. +// +// Solidity: function setPortableAddress(address addr) returns() +func (_Datahub *DatahubSession) SetPortableAddress(addr common.Address) (*types.Transaction, error) { + return _Datahub.Contract.SetPortableAddress(&_Datahub.TransactOpts, addr) +} + +// SetPortableAddress is a paid mutator transaction binding the contract method 0xc6d05aee. +// +// Solidity: function setPortableAddress(address addr) returns() +func (_Datahub *DatahubTransactorSession) SetPortableAddress(addr common.Address) (*types.Transaction, error) { + return _Datahub.Contract.SetPortableAddress(&_Datahub.TransactOpts, addr) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Datahub *DatahubTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Datahub.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Datahub *DatahubSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Datahub.Contract.TransferOwnership(&_Datahub.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Datahub *DatahubTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Datahub.Contract.TransferOwnership(&_Datahub.TransactOpts, newOwner) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Datahub *DatahubTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Datahub.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Datahub *DatahubSession) Receive() (*types.Transaction, error) { + return _Datahub.Contract.Receive(&_Datahub.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Datahub *DatahubTransactorSession) Receive() (*types.Transaction, error) { + return _Datahub.Contract.Receive(&_Datahub.TransactOpts) +} + +// DatahubOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Datahub contract. +type DatahubOwnershipTransferredIterator struct { + Event *DatahubOwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *DatahubOwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(DatahubOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(DatahubOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *DatahubOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DatahubOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DatahubOwnershipTransferred represents a OwnershipTransferred event raised by the Datahub contract. +type DatahubOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Datahub *DatahubFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*DatahubOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Datahub.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &DatahubOwnershipTransferredIterator{contract: _Datahub.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Datahub *DatahubFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *DatahubOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Datahub.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(DatahubOwnershipTransferred) + if err := _Datahub.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Datahub *DatahubFilterer) ParseOwnershipTransferred(log types.Log) (*DatahubOwnershipTransferred, error) { + event := new(DatahubOwnershipTransferred) + if err := _Datahub.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DatahubRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the Datahub contract. +type DatahubRoleAdminChangedIterator struct { + Event *DatahubRoleAdminChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *DatahubRoleAdminChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(DatahubRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(DatahubRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *DatahubRoleAdminChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DatahubRoleAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DatahubRoleAdminChanged represents a RoleAdminChanged event raised by the Datahub contract. +type DatahubRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Datahub *DatahubFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*DatahubRoleAdminChangedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _Datahub.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + if err != nil { + return nil, err + } + return &DatahubRoleAdminChangedIterator{contract: _Datahub.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil +} + +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Datahub *DatahubFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *DatahubRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _Datahub.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(DatahubRoleAdminChanged) + if err := _Datahub.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Datahub *DatahubFilterer) ParseRoleAdminChanged(log types.Log) (*DatahubRoleAdminChanged, error) { + event := new(DatahubRoleAdminChanged) + if err := _Datahub.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DatahubRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the Datahub contract. +type DatahubRoleGrantedIterator struct { + Event *DatahubRoleGranted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *DatahubRoleGrantedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(DatahubRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(DatahubRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *DatahubRoleGrantedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DatahubRoleGrantedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DatahubRoleGranted represents a RoleGranted event raised by the Datahub contract. +type DatahubRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Datahub *DatahubFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*DatahubRoleGrantedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _Datahub.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &DatahubRoleGrantedIterator{contract: _Datahub.contract, event: "RoleGranted", logs: logs, sub: sub}, nil +} + +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Datahub *DatahubFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *DatahubRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _Datahub.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(DatahubRoleGranted) + if err := _Datahub.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Datahub *DatahubFilterer) ParseRoleGranted(log types.Log) (*DatahubRoleGranted, error) { + event := new(DatahubRoleGranted) + if err := _Datahub.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DatahubRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the Datahub contract. +type DatahubRoleRevokedIterator struct { + Event *DatahubRoleRevoked // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *DatahubRoleRevokedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(DatahubRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(DatahubRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *DatahubRoleRevokedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DatahubRoleRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DatahubRoleRevoked represents a RoleRevoked event raised by the Datahub contract. +type DatahubRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Datahub *DatahubFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*DatahubRoleRevokedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _Datahub.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &DatahubRoleRevokedIterator{contract: _Datahub.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil +} + +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Datahub *DatahubFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *DatahubRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _Datahub.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(DatahubRoleRevoked) + if err := _Datahub.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Datahub *DatahubFilterer) ParseRoleRevoked(log types.Log) (*DatahubRoleRevoked, error) { + event := new(DatahubRoleRevoked) + if err := _Datahub.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/pkg/dfs/api.go b/pkg/dfs/api.go index e5a994c6..f4595db1 100644 --- a/pkg/dfs/api.go +++ b/pkg/dfs/api.go @@ -22,6 +22,9 @@ import ( "io" "time" + "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager" + "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc" + "github.com/plexsysio/taskmanager" "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" @@ -42,11 +45,12 @@ type API struct { users *user.Users logger logging.Logger tm *taskmanager.TaskManager + sm subscriptionManager.SubscriptionManager io.Closer } // NewDfsAPI is the main entry point for the df controller. -func NewDfsAPI(apiUrl, postageBlockId string, ensConfig *contracts.Config, logger logging.Logger) (*API, error) { +func NewDfsAPI(apiUrl, postageBlockId string, ensConfig *contracts.ENSConfig, subConfig *contracts.SubscriptionConfig, logger logging.Logger) (*API, error) { ens, err := ethClient.New(ensConfig, logger) if err != nil { if errors.Is(err, ethClient.ErrWrongChainID) { @@ -54,12 +58,21 @@ func NewDfsAPI(apiUrl, postageBlockId string, ensConfig *contracts.Config, logge } return nil, errEthClient } - c := bee.NewBeeClient(apiUrl, postageBlockId, logger) + c := bee.NewBeeClient(apiUrl, postageBlockId, false, logger) if !c.CheckConnection() { return nil, ErrBeeClient } users := user.NewUsers(c, ens, logger) + var sm subscriptionManager.SubscriptionManager + if subConfig != nil { + sm, err = rpc.New(subConfig, logger, c, c) + if err != nil { + logger.Errorf("subscriptionManager initialisation failed %s", err.Error()) + return nil, errSubManager + } + } + // discard tm logs as it creates too much noise tmLogger := logging.New(io.Discard, 0) @@ -68,6 +81,7 @@ func NewDfsAPI(apiUrl, postageBlockId string, ensConfig *contracts.Config, logge users: users, logger: logger, tm: taskmanager.New(10, defaultMaxWorkers, time.Second*15, tmLogger), + sm: sm, }, nil } diff --git a/pkg/dfs/doc_api.go b/pkg/dfs/doc_api.go index e394e79a..c2de067d 100644 --- a/pkg/dfs/doc_api.go +++ b/pkg/dfs/doc_api.go @@ -26,12 +26,7 @@ func (a *API) DocCreate(sessionId, podName, name string, indexes map[string]coll return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -47,12 +42,7 @@ func (a *API) DocOpen(sessionId, podName, name string) error { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -68,12 +58,7 @@ func (a *API) DocDelete(sessionId, podName, name string) error { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -90,12 +75,7 @@ func (a *API) DocList(sessionId, podName string) (map[string]collection.DBSchema return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } @@ -113,12 +93,7 @@ func (a *API) DocCount(sessionId, podName, name, expr string) (*collection.Table return keyCount, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return keyCount, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return keyCount, err } @@ -140,12 +115,7 @@ func (a *API) DocPut(sessionId, podName, name string, value []byte) error { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -162,12 +132,7 @@ func (a *API) DocGet(sessionId, podName, name, id string) ([]byte, error) { return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } @@ -184,12 +149,7 @@ func (a *API) DocDel(sessionId, podName, name, id string) error { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -206,12 +166,7 @@ func (a *API) DocFind(sessionId, podName, name, expr string, limit int) ([][]byt return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } @@ -227,12 +182,7 @@ func (a *API) DocBatch(sessionId, podName, name string) (*collection.DocBatch, e return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } @@ -248,12 +198,7 @@ func (a *API) DocBatchPut(sessionId, podName string, doc []byte, docBatch *colle return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -269,12 +214,7 @@ func (a *API) DocBatchWrite(sessionId, podName string, docBatch *collection.DocB return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -290,18 +230,13 @@ func (a *API) DocIndexJson(sessionId, podName, name, podFileWithPath string) err return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - // check if file present - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } file := podInfo.GetFile() - if !file.IsFileAlreadyPresent(podFileWithPath) { + if !file.IsFileAlreadyPresent(podInfo.GetPodPassword(), podFileWithPath) { return ErrFileNotPresent } diff --git a/pkg/dfs/errors.go b/pkg/dfs/errors.go index 2a88b094..ae564b42 100644 --- a/pkg/dfs/errors.go +++ b/pkg/dfs/errors.go @@ -29,7 +29,9 @@ var ( ErrFileAlreadyPresent = errors.New("file already exist with new name") //ErrBeeClient - ErrBeeClient = errors.New("could not connect to bee client") - errEthClient = errors.New("could not connect to eth backend") - errReadOnlyPod = errors.New("operation not permitted: read only pod") + ErrBeeClient = errors.New("could not connect to bee client") + errEthClient = errors.New("could not connect to eth backend") + errSubManager = errors.New("subscription manager initialisation failed") + errNilSubManager = errors.New("subscription manager not initialised") + errReadOnlyPod = errors.New("operation not permitted: read only pod") ) diff --git a/pkg/dfs/fs_api.go b/pkg/dfs/fs_api.go index df8ff46e..ea1eef51 100644 --- a/pkg/dfs/fs_api.go +++ b/pkg/dfs/fs_api.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "path/filepath" + "strings" "github.com/fairdatasociety/fairOS-dfs/pkg/dir" f "github.com/fairdatasociety/fairOS-dfs/pkg/file" @@ -30,25 +31,20 @@ import ( // Mkdir is a controller function which validates if the user is logged-in, // pod is open and calls the make directory function in the dir object. -func (a *API) Mkdir(podName, dirToCreateWithPath, sessionId string) error { +func (a *API) Mkdir(podName, dirToCreateWithPath, sessionId string, mode uint32) error { // get the logged-in user information ui := a.users.GetLoggedInUserInfo(sessionId) if ui == nil { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - // get the dir object and make directory - podInfo, podPassword, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, podPassword, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } directory := podInfo.GetDirectory() - return directory.MkDir(dirToCreateWithPath, podPassword) + return directory.MkDir(dirToCreateWithPath, podPassword, mode) } // RenameDir is a controller function which validates if the user is logged-in, @@ -60,13 +56,8 @@ func (a *API) RenameDir(podName, dirToRenameWithPath, newName, sessionId string) return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - // get the dir object and rename directory - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -83,13 +74,8 @@ func (a *API) IsDirPresent(podName, directoryNameWithPath, sessionId string) (bo return false, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return false, ErrPodNotOpen - } - // get pod Info - podInfo, podPassword, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, podPassword, err := ui.GetPod().GetPodInfo(podName) if err != nil { return false, err } @@ -108,13 +94,8 @@ func (a *API) RmDir(podName, directoryNameWithPath, sessionId string) error { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - // get the dir object and remove directory - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -131,13 +112,8 @@ func (a *API) ListDir(podName, currentDir, sessionId string) ([]dir.Entry, []f.E return nil, nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, nil, ErrPodNotOpen - } - // get the dir object and list directory - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, nil, err } @@ -145,7 +121,7 @@ func (a *API) ListDir(podName, currentDir, sessionId string) ([]dir.Entry, []f.E // check if directory present totalPath := utils.CombinePathAndFile(currentDir, "") - if directory.GetDirFromDirectoryMap(totalPath) == nil { + if directory.GetInode(podInfo.GetPodPassword(), totalPath) == nil { return nil, nil, dir.ErrDirectoryNotPresent } dEntries, fileList, err := directory.ListDir(currentDir, podInfo.GetPodPassword()) @@ -162,29 +138,40 @@ func (a *API) ListDir(podName, currentDir, sessionId string) ([]dir.Entry, []f.E // DirectoryStat is a controller function which validates if the user is logged-in, // pod is open and calls the dir object to get the information about the given directory. -func (a *API) DirectoryStat(podName, directoryName, sessionId string) (*dir.Stats, error) { +func (a *API) DirectoryStat(podName, directoryPath, sessionId string) (*dir.Stats, error) { // get the logged-in user information ui := a.users.GetLoggedInUserInfo(sessionId) if ui == nil { return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - // get the dir object and stat directory - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } directory := podInfo.GetDirectory() - ds, err := directory.DirStat(podName, podInfo.GetPodPassword(), directoryName) - if err != nil { - return nil, err + directoryPath = filepath.ToSlash(directoryPath) + if directoryPath != utils.PathSeparator { + parent := filepath.ToSlash(filepath.Dir(directoryPath)) + inode := directory.GetInode(podInfo.GetPodPassword(), parent) + if inode == nil { + return nil, dir.ErrDirectoryNotPresent + } + found := false + directoryName := filepath.Base(directoryPath) + for _, name := range inode.FileOrDirNames { + if strings.TrimPrefix(name, "_D_") == directoryName { + found = true + break + } + } + if !found { + return nil, dir.ErrDirectoryNotPresent + } } - return ds, nil + + return directory.DirStat(podName, podInfo.GetPodPassword(), directoryPath) } // DirectoryInode is a controller function which validates if the user is logged-in, @@ -196,18 +183,13 @@ func (a *API) DirectoryInode(podName, directoryName, sessionId string) (*dir.Ino return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - // get the dir object and stat directory - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } directory := podInfo.GetDirectory() - inode := directory.GetDirFromDirectoryMap(directoryName) + inode := directory.GetInode(podInfo.GetPodPassword(), directoryName) if inode == nil { a.logger.Errorf("dir not found: %s", directoryName) return nil, fmt.Errorf("dir not found") @@ -224,18 +206,8 @@ func (a *API) ChmodDir(podName, directoryNameWithPath, sessionId string, mode ui return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - // check if logged-in to pod - if !ui.GetPod().IsPodOpened(podName) { - return fmt.Errorf("login to pod to do this operation") - } - // get podInfo and construct the path - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -255,12 +227,7 @@ func (a *API) DeleteFile(podName, podFileWithPath, sessionId string) error { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -281,7 +248,7 @@ func (a *API) DeleteFile(podName, podFileWithPath, sessionId string) error { } // update the directory by removing the file from it - fileDir := filepath.Dir(podFileWithPath) + fileDir := filepath.ToSlash(filepath.Dir(podFileWithPath)) fileName := filepath.Base(podFileWithPath) return directory.RemoveEntryFromDir(fileDir, podInfo.GetPodPassword(), fileName, true) } @@ -295,50 +262,51 @@ func (a *API) FileStat(podName, podFileWithPath, sessionId string) (*f.Stats, er return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } - file := podInfo.GetFile() - ds, err := file.GetStats(podName, podFileWithPath, podInfo.GetPodPassword()) - if err != nil { - return nil, err + podFileWithPath = filepath.ToSlash(podFileWithPath) + directory := podInfo.GetDirectory() + inode := directory.GetInode(podInfo.GetPodPassword(), filepath.ToSlash(filepath.Dir(podFileWithPath))) + if inode != nil { + found := false + fileName := filepath.Base(podFileWithPath) + for _, name := range inode.FileOrDirNames { + if strings.TrimPrefix(name, "_F_") == fileName { + found = true + break + } + } + if !found { + return nil, f.ErrFileNotFound + } } - return ds, nil + + file := podInfo.GetFile() + return file.GetStats(podName, podFileWithPath, podInfo.GetPodPassword()) } // UploadFile is a controller function which validates if the user is logged-in, // // pod is open and calls the upload function. -func (a *API) UploadFile(podName, podFileName, sessionId string, fileSize int64, fd io.Reader, podPath, compression string, blockSize uint32, overwrite bool) error { +func (a *API) UploadFile(podName, podFileName, sessionId string, fileSize int64, fd io.Reader, podPath, compression string, blockSize, mode uint32, overwrite bool) error { // get the logged-in user information ui := a.users.GetLoggedInUserInfo(sessionId) if ui == nil { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } file := podInfo.GetFile() directory := podInfo.GetDirectory() podPath = filepath.ToSlash(podPath) - // check if file exists, then backup the file totalPath := utils.CombinePathAndFile(podPath, podFileName) - alreadyPresent := file.IsFileAlreadyPresent(totalPath) - + alreadyPresent := file.IsFileAlreadyPresent(podInfo.GetPodPassword(), totalPath) if alreadyPresent { if !overwrite { m, err := file.BackupFromFileName(totalPath, podInfo.GetPodPassword()) @@ -355,8 +323,7 @@ func (a *API) UploadFile(podName, podFileName, sessionId string, fileSize int64, return err } } - - err = file.Upload(fd, podFileName, fileSize, blockSize, podPath, compression, podInfo.GetPodPassword()) + err = file.Upload(fd, podFileName, fileSize, blockSize, mode, podPath, compression, podInfo.GetPodPassword()) if err != nil { return err } @@ -375,12 +342,7 @@ func (a *API) RenameFile(podName, fileNameWithPath, newFileNameWithPath, session return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -391,10 +353,10 @@ func (a *API) RenameFile(podName, fileNameWithPath, newFileNameWithPath, session newFileNameWithPath = filepath.ToSlash(newFileNameWithPath) // check if file exists - if !file.IsFileAlreadyPresent(fileNameWithPath) { + if !file.IsFileAlreadyPresent(podInfo.GetPodPassword(), fileNameWithPath) { return ErrFileNotPresent } - if file.IsFileAlreadyPresent(newFileNameWithPath) { + if file.IsFileAlreadyPresent(podInfo.GetPodPassword(), newFileNameWithPath) { return ErrFileAlreadyPresent } @@ -423,18 +385,8 @@ func (a *API) DownloadFile(podName, podFileWithPath, sessionId string) (io.ReadC return nil, 0, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, 0, ErrPodNotOpen - } - - // check if logged-in to pod - if !ui.GetPod().IsPodOpened(podName) { - return nil, 0, fmt.Errorf("login to pod to do this operation") - } - // get podInfo and construct the path - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, 0, err } @@ -458,19 +410,14 @@ func (a *API) WriteAtFile(podName, fileNameWithPath, sessionId string, update io return 0, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return 0, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return 0, err } file := podInfo.GetFile() fileNameWithPath = filepath.ToSlash(fileNameWithPath) // check if file exists - if !file.IsFileAlreadyPresent(fileNameWithPath) { + if !file.IsFileAlreadyPresent(podInfo.GetPodPassword(), fileNameWithPath) { return 0, ErrFileNotPresent } @@ -486,18 +433,8 @@ func (a *API) ReadSeekCloser(podName, podFileWithPath, sessionId string) (io.Rea return nil, 0, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, 0, ErrPodNotOpen - } - - // check if logged-in to pod - if !ui.GetPod().IsPodOpened(podName) { - return nil, 0, fmt.Errorf("login to pod to do this operation") - } - // get podInfo and construct the path - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, 0, err } @@ -520,13 +457,8 @@ func (a *API) ShareFile(podName, podFileWithPath, destinationUser, sessionId str return "", ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return "", ErrPodNotOpen - } - // get podInfo and construct the path - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return "", err } @@ -541,31 +473,26 @@ func (a *API) ShareFile(podName, podFileWithPath, destinationUser, sessionId str // ReceiveFile is a controller function which validates if the user is logged-in, // pod is open and calls the ReceiveFile function to get the shared file in to the // given pod. -func (a *API) ReceiveFile(podName, sessionId string, sharingRef utils.SharingReference, dir string) (string, error) { +func (a *API) ReceiveFile(podName, sessionId, ref string, dir string) (string, error) { // get the logged-in user information ui := a.users.GetLoggedInUserInfo(sessionId) if ui == nil { return "", ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return "", ErrPodNotOpen - } - - return a.users.ReceiveFileFromUser(podName, sharingRef, ui, ui.GetPod(), dir) + return a.users.ReceiveFileFromUser(podName, ref, ui, ui.GetPod(), dir) } // ReceiveInfo is a controller function which validates if the user is logged-in, // calls the ReceiveInfo function to display the shared file's information. -func (a *API) ReceiveInfo(sessionId string, sharingRef utils.SharingReference) (*user.ReceiveFileInfo, error) { +func (a *API) ReceiveInfo(sessionId, ref string) (*user.ReceiveFileInfo, error) { // get the logged-in user information ui := a.users.GetLoggedInUserInfo(sessionId) if ui == nil { return nil, ErrUserNotLoggedIn } - return a.users.ReceiveFileInfo(sharingRef) + return a.users.ReceiveFileInfo(ref) } // StatusFile is a controller function which validates if the user is logged-in, @@ -577,18 +504,8 @@ func (a *API) StatusFile(podName, podFileWithPath, sessionId string) (int64, int return 0, 0, 0, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return 0, 0, 0, ErrPodNotOpen - } - - // check if logged-in to pod - if !ui.GetPod().IsPodOpened(podName) { - return 0, 0, 0, fmt.Errorf("login to pod to do this operation") - } - // get podInfo and construct the path - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return 0, 0, 0, err } @@ -607,18 +524,8 @@ func (a *API) ChmodFile(podName, podFileWithPath, sessionId string, mode uint32) return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - // check if logged-in to pod - if !ui.GetPod().IsPodOpened(podName) { - return fmt.Errorf("login to pod to do this operation") - } - // get podInfo and construct the path - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } diff --git a/pkg/dfs/kv_api.go b/pkg/dfs/kv_api.go index 43e80c38..e1d52760 100644 --- a/pkg/dfs/kv_api.go +++ b/pkg/dfs/kv_api.go @@ -28,12 +28,7 @@ func (a *API) KVCreate(sessionId, podName, name string, indexType collection.Ind return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -49,12 +44,7 @@ func (a *API) KVDelete(sessionId, podName, name string) error { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -70,12 +60,7 @@ func (a *API) KVOpen(sessionId, podName, name string) error { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -91,11 +76,7 @@ func (a *API) KVList(sessionId, podName string) (map[string][]string, error) { return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } @@ -111,12 +92,7 @@ func (a *API) KVCount(sessionId, podName, name string) (*collection.TableKeyCoun return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } @@ -132,12 +108,7 @@ func (a *API) KVPut(sessionId, podName, name, key string, value []byte) error { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -153,12 +124,7 @@ func (a *API) KVGet(sessionId, podName, name, key string) ([]string, []byte, err return nil, nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, nil, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, nil, err } @@ -174,11 +140,7 @@ func (a *API) KVDel(sessionId, podName, name, key string) ([]byte, error) { return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } @@ -194,12 +156,7 @@ func (a *API) KVBatch(sessionId, podName, name string, columns []string) (*colle return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } @@ -215,11 +172,6 @@ func (a *API) KVBatchPut(sessionId, podName, key string, value []byte, batch *co return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - return batch.Put(key, value, false, false) } @@ -231,11 +183,6 @@ func (a *API) KVBatchWrite(sessionId, podName string, batch *collection.Batch) e return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - _, err := batch.Write("") return err } @@ -248,12 +195,7 @@ func (a *API) KVSeek(sessionId, podName, name, start, end string, limit int64) ( return nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } @@ -269,12 +211,7 @@ func (a *API) KVGetNext(sessionId, podName, name string) ([]string, string, []by return nil, "", nil, ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return nil, "", nil, ErrPodNotOpen - } - - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, "", nil, err } diff --git a/pkg/dfs/pod_api.go b/pkg/dfs/pod_api.go index 6d299b56..64d6b432 100644 --- a/pkg/dfs/pod_api.go +++ b/pkg/dfs/pod_api.go @@ -19,8 +19,23 @@ package dfs import ( "context" "encoding/hex" - + "encoding/json" + "fmt" + "io" + "net/http" + "path/filepath" + "strconv" + "strings" + + c "github.com/fairdatasociety/fairOS-dfs/pkg/collection" + + "github.com/fairdatasociety/fairOS-dfs/pkg/account" + "github.com/fairdatasociety/fairOS-dfs/pkg/contracts/datahub" + "github.com/fairdatasociety/fairOS-dfs/pkg/dir" + "github.com/fairdatasociety/fairOS-dfs/pkg/feed" + "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/pod" + "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc" "github.com/fairdatasociety/fairOS-dfs/pkg/user" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" ) @@ -54,7 +69,7 @@ func (a *API) DeletePod(podName, sessionId string) error { // delete all the directory, files, and database tables under this pod from // the Swarm network. - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return err } @@ -68,11 +83,8 @@ func (a *API) DeletePod(podName, sessionId string) error { return err } - // close the pod if it is open - if ui.IsPodOpen(podName) { - // remove from the login session - ui.RemovePodName(podName) - } + // remove from the login session + ui.RemovePodName(podName) return nil } @@ -87,12 +99,7 @@ func (a *API) DeletePod(podName, sessionId string) error { return err } - // close the pod if it is open - if ui.IsPodOpen(podName) { - // remove from the login session - ui.RemovePodName(podName) - } - + ui.RemovePodName(podName) return nil } @@ -103,55 +110,13 @@ func (a *API) OpenPod(podName, sessionId string) (*pod.Info, error) { if ui == nil { return nil, ErrUserNotLoggedIn } - // return if pod already open - if ui.IsPodOpen(podName) { - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) - if err != nil { - return nil, err - } - return podInfo, nil - } - // open the pod - pi, err := ui.GetPod().OpenPod(podName) - if err != nil { - return nil, err - } - err = pi.GetDirectory().AddRootDir(pi.GetPodName(), pi.GetPodPassword(), pi.GetPodAddress(), pi.GetFeed()) + podInfo, _, err := ui.GetPod().GetPodInfo(podName) if err != nil { return nil, err } // Add podName in the login user session - ui.AddPodName(podName, pi) - return pi, nil -} - -// OpenPodAsync -func (a *API) OpenPodAsync(ctx context.Context, podName, sessionId string) (*pod.Info, error) { - // get the logged-in user information - ui := a.users.GetLoggedInUserInfo(sessionId) - if ui == nil { - return nil, ErrUserNotLoggedIn - } - // return if pod already open - if ui.IsPodOpen(podName) { - podInfo, _, err := ui.GetPod().GetPodInfoFromPodMap(podName) - if err != nil { - return nil, err - } - return podInfo, nil - } - // open the pod - pi, err := ui.GetPod().OpenPodAsync(ctx, podName) - if err != nil { - return nil, err - } - err = pi.GetDirectory().AddRootDir(pi.GetPodName(), pi.GetPodPassword(), pi.GetPodAddress(), pi.GetFeed()) - if err != nil { - return nil, err - } - // Add podName in the login user session - ui.AddPodName(podName, pi) - return pi, nil + ui.AddPodName(podName, podInfo) + return podInfo, nil } // ClosePod @@ -162,11 +127,6 @@ func (a *API) ClosePod(podName, sessionId string) error { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - // close the pod err := ui.GetPod().ClosePod(podName) if err != nil { @@ -202,11 +162,6 @@ func (a *API) SyncPod(podName, sessionId string) error { return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - // sync the pod err := ui.GetPod().SyncPod(podName) if err != nil { @@ -223,11 +178,6 @@ func (a *API) SyncPodAsync(ctx context.Context, podName, sessionId string) error return ErrUserNotLoggedIn } - // check if pod open - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - // sync the pod err := ui.GetPod().SyncPodAsync(ctx, podName) if err != nil { @@ -291,6 +241,175 @@ func (a *API) PodReceiveInfo(sessionId string, ref utils.Reference) (*pod.ShareI return ui.GetPod().ReceivePodInfo(ref) } +// PublicPodReceiveInfo +func (a *API) PublicPodReceiveInfo(ref utils.Reference) (*pod.ShareInfo, error) { + data, resp, err := a.client.DownloadBlob(ref.Bytes()) + if err != nil { // skipcq: TCV-001 + return nil, err + } + + if resp != http.StatusOK { // skipcq: TCV-001 + return nil, fmt.Errorf("ReceivePodInfo: could not download blob") + } + + var shareInfo *pod.ShareInfo + err = json.Unmarshal(data, &shareInfo) + if err != nil { + return nil, err + } + + return shareInfo, nil +} + +// PublicPodFileDownload +func (a *API) PublicPodFileDownload(pod *pod.ShareInfo, filePath string) (io.ReadCloser, uint64, error) { + + accountInfo := &account.Info{} + address := utils.HexToAddress(pod.Address) + accountInfo.SetAddress(address) + + fd := feed.New(accountInfo, a.client, a.logger) + topic := utils.HashString(filePath) + _, metaBytes, err := fd.GetFeedData(topic, accountInfo.GetAddress(), []byte(pod.Password)) + if err != nil { + return nil, 0, err + } + + if string(metaBytes) == utils.DeletedFeedMagicWord { + a.logger.Errorf("found deleted feed for %s\n", filePath) + return nil, 0, file.ErrDeletedFeed + } + + var meta *file.MetaData + err = json.Unmarshal(metaBytes, &meta) + if err != nil { // skipcq: TCV-001 + return nil, 0, err + } + + fileInodeBytes, _, err := a.client.DownloadBlob(meta.InodeAddress) + if err != nil { // skipcq: TCV-001 + return nil, 0, err + } + + var fileInode file.INode + err = json.Unmarshal(fileInodeBytes, &fileInode) + if err != nil { // skipcq: TCV-001 + return nil, 0, err + } + + reader := file.NewReader(fileInode, a.client, meta.Size, meta.BlockSize, meta.Compression, false) + return reader, meta.Size, nil +} + +// PublicPodKVEntryGet +func (a *API) PublicPodKVEntryGet(pod *pod.ShareInfo, name, key string) ([]string, []byte, error) { + + accountInfo := &account.Info{} + address := utils.HexToAddress(pod.Address) + accountInfo.SetAddress(address) + + fd := feed.New(accountInfo, a.client, a.logger) + kvStore := c.NewKeyValueStore(pod.PodName, fd, accountInfo, address, a.client, a.logger) + + err := kvStore.OpenKVTable(name, pod.Password) + if err != nil { + return nil, nil, err + } + + return kvStore.KVGet(name, key) +} + +// PublicPodFileDownload +func (a *API) PublicPodDisLs(pod *pod.ShareInfo, dirPathToLs string) ([]dir.Entry, []file.Entry, error) { + + accountInfo := &account.Info{} + address := utils.HexToAddress(pod.Address) + accountInfo.SetAddress(address) + + fd := feed.New(accountInfo, a.client, a.logger) + + dirNameWithPath := filepath.ToSlash(dirPathToLs) + topic := utils.HashString(dirNameWithPath) + _, data, err := fd.GetFeedData(topic, accountInfo.GetAddress(), []byte(pod.Password)) + if err != nil { // skipcq: TCV-001 + if dirNameWithPath == utils.PathSeparator { + return nil, nil, nil + } + return nil, nil, fmt.Errorf("list dir : %v", err) // skipcq: TCV-001 + } + + dirInode := &dir.Inode{} + err = dirInode.Unmarshal(data) + if err != nil { + return nil, nil, fmt.Errorf("list dir : %v", err) + } + + listEntries := []dir.Entry{} + var files []string + for _, fileOrDirName := range dirInode.FileOrDirNames { + if strings.HasPrefix(fileOrDirName, "_D_") { + dirName := strings.TrimPrefix(fileOrDirName, "_D_") + dirPath := utils.CombinePathAndFile(dirNameWithPath, dirName) + dirTopic := utils.HashString(dirPath) + + _, data, err := fd.GetFeedData(dirTopic, accountInfo.GetAddress(), []byte(pod.Password)) + if err != nil { // skipcq: TCV-001 + return nil, nil, fmt.Errorf("list dir : %v", err) + } + var dirInode *dir.Inode + err = json.Unmarshal(data, &dirInode) + if err != nil { // skipcq: TCV-001 + return nil, nil, fmt.Errorf("list dir : %v", err) + } + entry := dir.Entry{ + Name: dirInode.Meta.Name, + ContentType: dir.MineTypeDirectory, // per RFC2425 + CreationTime: strconv.FormatInt(dirInode.Meta.CreationTime, 10), + AccessTime: strconv.FormatInt(dirInode.Meta.AccessTime, 10), + ModificationTime: strconv.FormatInt(dirInode.Meta.ModificationTime, 10), + Mode: dirInode.Meta.Mode, + } + listEntries = append(listEntries, entry) + } else if strings.HasPrefix(fileOrDirName, "_F_") { + fileName := strings.TrimPrefix(fileOrDirName, "_F_") + filePath := utils.CombinePathAndFile(dirNameWithPath, fileName) + files = append(files, filePath) + } + } + + fileEntries := []file.Entry{} + for _, filePath := range files { + fileTopic := utils.HashString(utils.CombinePathAndFile(filePath, "")) + + _, data, err := fd.GetFeedData(fileTopic, accountInfo.GetAddress(), []byte(pod.Password)) + if err != nil { // skipcq: TCV-001 + return nil, nil, fmt.Errorf("file mtdt : %v", err) + } + if string(data) == utils.DeletedFeedMagicWord { // skipcq: TCV-001 + continue + } + var meta *file.MetaData + err = json.Unmarshal(data, &meta) + if err != nil { // skipcq: TCV-001 + return nil, nil, fmt.Errorf("file mtdt : %v", err) + } + entry := file.Entry{ + Name: meta.Name, + ContentType: meta.ContentType, + Size: strconv.FormatUint(meta.Size, 10), + BlockSize: strconv.FormatInt(int64(meta.BlockSize), 10), + CreationTime: strconv.FormatInt(meta.CreationTime, 10), + AccessTime: strconv.FormatInt(meta.AccessTime, 10), + ModificationTime: strconv.FormatInt(meta.ModificationTime, 10), + Mode: meta.Mode, + } + + fileEntries = append(fileEntries, entry) + } + + return listEntries, fileEntries, nil +} + // PodReceive func (a *API) PodReceive(sessionId, sharedPodName string, ref utils.Reference) (*pod.Info, error) { // get the logged-in user information @@ -319,10 +438,6 @@ func (a *API) ForkPod(podName, forkName, sessionId string) error { return ErrUserNotLoggedIn } - if !ui.IsPodOpen(podName) { - return ErrPodNotOpen - } - if forkName == "" { return pod.ErrBlankPodName } @@ -382,11 +497,261 @@ func (a *API) prepareOwnPod(ui *user.Info, podName string) (*pod.Info, error) { return nil, err } - // create the root directory - err = pi.GetDirectory().MkRootDir(pi.GetPodName(), podPassword, pi.GetPodAddress(), pi.GetFeed()) + return pi, nil +} + +// ListPodInMarketplace +func (a *API) ListPodInMarketplace(sessionId, podName, title, desc, thumbnail string, price uint64, daysValid uint16, category [32]byte) error { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return ErrUserNotLoggedIn + } + + if a.sm == nil { + return errNilSubManager + } + + nameHash, err := a.users.GetNameHash(ui.GetUserName()) + if err != nil { + return err + } + + return ui.GetPod().ListPodInMarketplace(podName, title, desc, thumbnail, price, daysValid, category, nameHash) +} + +// ChangePodListStatusInMarketplace +func (a *API) ChangePodListStatusInMarketplace(sessionId string, subHash [32]byte, show bool) error { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return ErrUserNotLoggedIn + } + + if a.sm == nil { + return errNilSubManager + } + + return ui.GetPod().PodStatusInMarketplace(subHash, show) +} + +// RequestSubscription +func (a *API) RequestSubscription(sessionId string, subHash [32]byte) error { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return ErrUserNotLoggedIn + } + + if a.sm == nil { + return errNilSubManager + } + + nameHash, err := a.users.GetNameHash(ui.GetUserName()) + if err != nil { + return err + } + + return ui.GetPod().RequestSubscription(subHash, nameHash) +} + +// ApproveSubscription +func (a *API) ApproveSubscription(sessionId, podName string, reqHash, nameHash [32]byte) error { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return ErrUserNotLoggedIn + } + + if a.sm == nil { + return errNilSubManager + } + + _, subscriberPublicKey, err := a.users.GetUserInfoFromENS(nameHash) + if err != nil { + return err + } + + return ui.GetPod().ApproveSubscription(podName, reqHash, subscriberPublicKey) +} + +// EncryptSubscription +func (a *API) EncryptSubscription(sessionId, podName string, nameHash [32]byte) (string, error) { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return "", ErrUserNotLoggedIn + } + + if a.sm == nil { + return "", errNilSubManager + } + + _, subscriberPublicKey, err := a.users.GetUserInfoFromENS(nameHash) + if err != nil { + return "", err + } + + return ui.GetPod().EncryptUploadSubscriptionInfo(podName, subscriberPublicKey) +} + +// DecryptAndOpenSubscriptionPod +func (a *API) DecryptAndOpenSubscriptionPod(sessionId, reference string, sellerNameHash [32]byte) (*pod.Info, error) { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return nil, ErrUserNotLoggedIn + } + + if a.sm == nil { + return nil, errNilSubManager + } + + _, publicKey, err := a.users.GetUserInfoFromENS(sellerNameHash) + if err != nil { + return nil, err + } + + pi, err := ui.GetPod().OpenSubscribedPodFromReference(reference, publicKey) + if err != nil { + return nil, err + } + + err = pi.GetDirectory().AddRootDir(pi.GetPodName(), pi.GetPodPassword(), pi.GetPodAddress(), pi.GetFeed()) + if err != nil { + return nil, err + } + // Add podName in the login user session + ui.AddPodName(pi.GetPodName(), pi) + return pi, nil + +} + +type SubscriptionInfo struct { + SubHash [32]byte + PodName string + PodAddress string + Category string + InfoLocation []byte + ValidTill int64 +} + +// GetSubscriptions +func (a *API) GetSubscriptions(sessionId string) ([]SubscriptionInfo, error) { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return nil, ErrUserNotLoggedIn + } + + if a.sm == nil { + return nil, errNilSubManager + } + + nameHash, err := a.users.GetNameHash(ui.GetUserName()) + if err != nil { + return nil, err + } + + subscriptions, err := ui.GetPod().GetSubscriptions(nameHash) if err != nil { return nil, err } + subs := make([]SubscriptionInfo, len(subscriptions)) + for i, item := range subscriptions { + info, err := ui.GetPod().GetSubscribablePodInfo(item.SubHash) + if err != nil { + return subs, err + } + var infoLocation = make([]byte, 32) + copy(infoLocation, item.UnlockKeyLocation[:]) + sub := SubscriptionInfo{ + SubHash: item.SubHash, + PodName: info.PodName, + PodAddress: info.PodAddress, + InfoLocation: infoLocation, + ValidTill: item.ValidTill.Int64(), + Category: info.Category, + } + + subs[i] = sub + } + + return subs, nil +} + +// GetSubscribablePodInfo +func (a *API) GetSubscribablePodInfo(sessionId string, subHash [32]byte) (*rpc.SubscriptionItemInfo, error) { + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return nil, ErrUserNotLoggedIn + } + if a.sm == nil { + return nil, errNilSubManager + } + return a.sm.GetSubscribablePodInfo(subHash) +} + +// OpenSubscribedPod +func (a *API) OpenSubscribedPod(sessionId string, subHash [32]byte, infoLocation string) (*pod.Info, error) { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return nil, ErrUserNotLoggedIn + } + + if a.sm == nil { + return nil, errNilSubManager + } + sub, err := a.sm.GetSub(subHash) + if err != nil { + return nil, err + } + + subHashString := utils.Encode(subHash[:]) + + _, ownerPublicKey, err := a.users.GetUserInfoFromENS(sub.FdpSellerNameHash) + if err != nil { + return nil, err + } + + // open the pod + pi, err := ui.GetPod().OpenSubscribedPodFromReference(infoLocation, ownerPublicKey) + if err != nil { + return nil, err + } + err = pi.GetDirectory().AddRootDir(pi.GetPodName(), pi.GetPodPassword(), pi.GetPodAddress(), pi.GetFeed()) + if err != nil { + return nil, err + } + // Add podName in the login user session + ui.AddPodName("0x"+subHashString, pi) return pi, nil } + +// GetSubscribablePods +func (a *API) GetSubscribablePods(sessionId string) ([]datahub.DataHubSub, error) { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return nil, ErrUserNotLoggedIn + } + if a.sm == nil { + return nil, errNilSubManager + } + return ui.GetPod().GetMarketplace() +} + +// GetSubscribablePods +func (a *API) GetSubsRequests(sessionId string) ([]datahub.DataHubSubRequest, error) { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return nil, ErrUserNotLoggedIn + } + if a.sm == nil { + return nil, errNilSubManager + } + return ui.GetPod().GetSubRequests() +} diff --git a/pkg/dfs/user_api.go b/pkg/dfs/user_api.go index 0924a713..79d0c261 100644 --- a/pkg/dfs/user_api.go +++ b/pkg/dfs/user_api.go @@ -22,17 +22,17 @@ import ( // CreateUserV2 is a controller function which calls the create user function from the user object. func (a *API) CreateUserV2(userName, passPhrase, mnemonic, sessionId string) (string, string, string, string, *user.Info, error) { - return a.users.CreateNewUserV2(userName, passPhrase, mnemonic, sessionId, a.tm) + return a.users.CreateNewUserV2(userName, passPhrase, mnemonic, sessionId, a.tm, a.sm) } // LoginUserV2 is a controller function which calls the users login function. func (a *API) LoginUserV2(userName, passPhrase, sessionId string) (*user.Info, string, string, error) { - return a.users.LoginUserV2(userName, passPhrase, a.client, a.tm, sessionId) + return a.users.LoginUserV2(userName, passPhrase, a.client, a.tm, a.sm, sessionId) } // LoadLiteUser is a controller function which loads user from mnemonic and doesn't store any user info on chain func (a *API) LoadLiteUser(userName, passPhrase, mnemonic, sessionId string) (string, string, *user.Info, error) { - return a.users.LoadLiteUser(userName, passPhrase, mnemonic, sessionId, a.tm) + return a.users.LoadLiteUser(userName, passPhrase, mnemonic, sessionId, a.tm, a.sm) } // LogoutUser is a controller function which gets the logged-in user information and logs it out. @@ -78,3 +78,23 @@ func (a *API) GetUserStat(sessionId string) (*user.Stat, error) { return a.users.GetUserStat(ui) } + +// ConnectPortableAccountWithWallet is a controller function which calls the users login function. +func (a *API) ConnectPortableAccountWithWallet(userName, passPhrase, addressHex, signature string) error { + return a.users.ConnectWallet(userName, passPhrase, addressHex, signature, a.client) +} + +// LoginWithWallet is a controller function which calls the users login function. +func (a *API) LoginWithWallet(addressHex, signature, sessionId string) (*user.Info, string, error) { + return a.users.LoginWithWallet(addressHex, signature, a.client, a.tm, a.sm, sessionId) +} + +// GetNameHash +func (a *API) GetNameHash(sessionId string, username string) ([32]byte, error) { + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return [32]byte{}, ErrUserNotLoggedIn + } + + return a.users.GetNameHash(username) +} diff --git a/pkg/dir/chmod_test.go b/pkg/dir/chmod_test.go index a10368c8..ae1e0c9e 100644 --- a/pkg/dir/chmod_test.go +++ b/pkg/dir/chmod_test.go @@ -49,15 +49,15 @@ func TestChmod(t *testing.T) { } // populate the directory with few directory and files - err := dirObject.MkDir("/dirToChmod", podPassword) + err := dirObject.MkDir("/dirToChmod", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/dirToChmod/subDir1", podPassword) + err = dirObject.MkDir("/dirToChmod/subDir1", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/dirToChmod/subDir2", podPassword) + err = dirObject.MkDir("/dirToChmod/subDir2", podPassword, 0) if err != nil { t.Fatal(err) } diff --git a/pkg/dir/dir_present_test.go b/pkg/dir/dir_present_test.go index b636d266..537bd627 100644 --- a/pkg/dir/dir_present_test.go +++ b/pkg/dir/dir_present_test.go @@ -66,7 +66,7 @@ func TestDirPresent(t *testing.T) { } // create a new dir - err := dirObject.MkDir("/baseDir", podPassword) + err := dirObject.MkDir("/baseDir", podPassword, 0) if err != nil { t.Fatal(err) } diff --git a/pkg/dir/dir_test.go b/pkg/dir/dir_test.go index 55a324d0..9f84ad6b 100644 --- a/pkg/dir/dir_test.go +++ b/pkg/dir/dir_test.go @@ -50,7 +50,7 @@ func TestDirRmAllFromMap(t *testing.T) { } // create a new dir - err := dirObject.MkDir("/baseDir", podPassword) + err := dirObject.MkDir("/baseDir", podPassword, 0) if err != nil { t.Fatal(err) } @@ -62,9 +62,18 @@ func TestDirRmAllFromMap(t *testing.T) { } dirObject.RemoveAllFromDirectoryMap() - node := dirObject.GetDirFromDirectoryMap("/baseDir") + node := dirObject.GetInode(podPassword, "/baseDir") + if node == nil { + t.Fatal("node should not be nil, metadata should be available in blockstore") + } + + err = dirObject.RmDir("/baseDir", podPassword) + if err != nil { + t.Fatal(err) + } + node = dirObject.GetInode(podPassword, "/baseDir") if node != nil { - t.Fatal("node should be nil") + t.Fatal("node should be nil") } }) } diff --git a/pkg/dir/inode.go b/pkg/dir/inode.go index 91e87d5b..5e8b2b92 100644 --- a/pkg/dir/inode.go +++ b/pkg/dir/inode.go @@ -63,3 +63,22 @@ func (in *Inode) Unmarshal(data []byte) error { } return nil } + +func (d *Directory) GetInode(podPassword, dirNameWithPath string) *Inode { + node := d.GetDirFromDirectoryMap(dirNameWithPath) + if node != nil { + return node + } + topic := utils.HashString(dirNameWithPath) + _, data, err := d.fd.GetFeedData(topic, d.getAddress(), []byte(podPassword)) + if err != nil { // skipcq: TCV-001 + return nil + } + var inode Inode + err = inode.Unmarshal(data) + if err != nil { // skipcq: TCV-001 + return nil + } + d.AddToDirectoryMap(dirNameWithPath, &inode) + return &inode +} diff --git a/pkg/dir/ls.go b/pkg/dir/ls.go index ec39ba09..8160a4b1 100644 --- a/pkg/dir/ls.go +++ b/pkg/dir/ls.go @@ -75,7 +75,7 @@ func (d *Directory) ListDir(dirNameWithPath, podPassword string) ([]Entry, []str lsTask := newLsTask(d, dirTopic, dirPath, podPassword, listEntries, mtx, wg) _, err := d.syncManager.Go(lsTask) if err != nil { - return nil, nil, fmt.Errorf("list dir : %v", err) + wg.Done() } } else if strings.HasPrefix(fileOrDirName, "_F_") { fileName := strings.TrimPrefix(fileOrDirName, "_F_") diff --git a/pkg/dir/ls_test.go b/pkg/dir/ls_test.go index 59a36e9c..89a7dd3a 100644 --- a/pkg/dir/ls_test.go +++ b/pkg/dir/ls_test.go @@ -67,7 +67,7 @@ func TestListDirectory(t *testing.T) { if err != nil { t.Fatal(err) } - err := dirObject.MkDir("/", podPassword) + err := dirObject.MkDir("/", podPassword, 0) if !errors.Is(err, dir.ErrInvalidDirectoryName) { t.Fatal("invalid dir name", err) } @@ -75,26 +75,26 @@ func TestListDirectory(t *testing.T) { if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/"+longDirName, podPassword) + err = dirObject.MkDir("/"+longDirName, podPassword, 0) if !errors.Is(err, dir.ErrTooLongDirectoryName) { t.Fatal("dir name too long") } // create some dir and files - err = dirObject.MkDir("/parentDir", podPassword) + err = dirObject.MkDir("/parentDir", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/parentDir", podPassword) + err = dirObject.MkDir("/parentDir", podPassword, 0) if !errors.Is(err, dir.ErrDirectoryAlreadyPresent) { t.Fatal("dir already present") } // populate the directory with few directory and files - err = dirObject.MkDir("/parentDir/subDir1", podPassword) + err = dirObject.MkDir("/parentDir/subDir1", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/parentDir/subDir2", podPassword) + err = dirObject.MkDir("/parentDir/subDir2", podPassword, 0) if err != nil { t.Fatal(err) } @@ -165,12 +165,12 @@ func TestListDirectory(t *testing.T) { } // create dir - err = dirObject.MkDir("/parentDir", podPassword) + err = dirObject.MkDir("/parentDir", podPassword, 0) if err != nil { t.Fatal(err) } // populate the directory with few directory and files - err = dirObject.MkDir("/parentDir/subDir1", podPassword) + err = dirObject.MkDir("/parentDir/subDir1", podPassword, 0) if err != nil { t.Fatal(err) } diff --git a/pkg/dir/mkdir.go b/pkg/dir/mkdir.go index 4acb1f1c..b84c90ac 100644 --- a/pkg/dir/mkdir.go +++ b/pkg/dir/mkdir.go @@ -34,7 +34,7 @@ const ( ) // MkDir -func (d *Directory) MkDir(dirToCreateWithPath, podPassword string) error { +func (d *Directory) MkDir(dirToCreateWithPath, podPassword string, mode uint32) error { parentPath := filepath.ToSlash(filepath.Dir(dirToCreateWithPath)) dirName := filepath.Base(dirToCreateWithPath) @@ -52,14 +52,17 @@ func (d *Directory) MkDir(dirToCreateWithPath, podPassword string) error { topic := utils.HashString(totalPath) // check if parent path exists - if d.GetDirFromDirectoryMap(parentPath) == nil { + if d.GetInode(podPassword, parentPath) == nil { return ErrDirectoryNotPresent } - if d.GetDirFromDirectoryMap(totalPath) != nil { + if d.GetInode(podPassword, totalPath) != nil { return ErrDirectoryAlreadyPresent } + if mode == 0 { + mode = S_IFDIR | defaultMode + } // create the meta data now := time.Now().Unix() meta := MetaData{ @@ -69,7 +72,7 @@ func (d *Directory) MkDir(dirToCreateWithPath, podPassword string) error { CreationTime: now, ModificationTime: now, AccessTime: now, - Mode: S_IFDIR | defaultMode, + Mode: mode, } dirInode := &Inode{ Meta: &meta, diff --git a/pkg/dir/mkdir_test.go b/pkg/dir/mkdir_test.go index d00f034a..e3b25f67 100644 --- a/pkg/dir/mkdir_test.go +++ b/pkg/dir/mkdir_test.go @@ -67,7 +67,7 @@ func TestMkdir(t *testing.T) { } // create a new dir - err := dirObject.MkDir("/baseDir", podPassword) + err := dirObject.MkDir("/baseDir", podPassword, 0) if err != nil { t.Fatal(err) } @@ -96,22 +96,22 @@ func TestMkdir(t *testing.T) { } // try to create a new dir without creating root - err := dirObject.MkDir("/baseDir/baseDir2/baseDir3/baseDir4", podPassword) + err := dirObject.MkDir("/baseDir/baseDir2/baseDir3/baseDir4", podPassword, 0) if err == nil || err != dir.ErrDirectoryNotPresent { t.Fatal(err) } - err = dirObject.MkDir("/baseDir", podPassword) + err = dirObject.MkDir("/baseDir", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/baseDir/baseDir2", podPassword) + err = dirObject.MkDir("/baseDir/baseDir2", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/baseDir/baseDir2/baseDir3", podPassword) + err = dirObject.MkDir("/baseDir/baseDir2/baseDir3", podPassword, 0) if err != nil { t.Fatal(err) } diff --git a/pkg/dir/modify_dir_entry.go b/pkg/dir/modify_dir_entry.go index ec22fc20..a1b64626 100644 --- a/pkg/dir/modify_dir_entry.go +++ b/pkg/dir/modify_dir_entry.go @@ -19,6 +19,7 @@ package dir import ( "encoding/json" "fmt" + "path/filepath" "time" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" @@ -37,24 +38,12 @@ func (d *Directory) AddEntryToDir(parentDir, podPassword, itemToAdd string, isFi return ErrInvalidFileOrDirectoryName } + dirInode := d.GetInode(podPassword, parentDir) // check if parent directory present - if d.GetDirFromDirectoryMap(parentDir) == nil { + if dirInode == nil { return ErrDirectoryNotPresent } - // get the latest meta from swarm - topic := utils.HashString(parentDir) - _, data, err := d.fd.GetFeedData(topic, d.userAddress, []byte(podPassword)) - if err != nil { // skipcq: TCV-001 - return fmt.Errorf("modify dir entry: %v", err) - } - - var dirInode Inode - err = json.Unmarshal(data, &dirInode) - if err != nil { // skipcq: TCV-001 - return fmt.Errorf("modify dir entry : %v", err) - } - // add file or directory entry if isFile { itemToAdd = "_F_" + itemToAdd @@ -65,15 +54,17 @@ func (d *Directory) AddEntryToDir(parentDir, podPassword, itemToAdd string, isFi dirInode.Meta.ModificationTime = time.Now().Unix() // update the feed of the dir and the data structure with the latest info - data, err = json.Marshal(dirInode) + data, err := json.Marshal(dirInode) if err != nil { // skipcq: TCV-001 return fmt.Errorf("modify dir entry : %v", err) } + + topic := utils.HashString(parentDir) _, err = d.fd.UpdateFeed(topic, d.userAddress, data, []byte(podPassword)) if err != nil { // skipcq: TCV-001 return fmt.Errorf("modify dir entry : %v", err) } - d.AddToDirectoryMap(parentDir, &dirInode) + d.AddToDirectoryMap(parentDir, dirInode) return nil } @@ -89,18 +80,15 @@ func (d *Directory) RemoveEntryFromDir(parentDir, podPassword, itemToDelete stri if itemToDelete == "" { // skipcq: TCV-001 return ErrInvalidFileOrDirectoryName } - - parentHash := utils.HashString(parentDir) - _, parentData, err := d.fd.GetFeedData(parentHash, d.userAddress, []byte(podPassword)) - if err != nil { // skipcq: TCV-001 - return err + parentDir = filepath.ToSlash(parentDir) + parentDirInode := d.GetInode(podPassword, parentDir) + // check if parent directory present + if parentDirInode == nil { + d.logger.Errorf("remove entry from dir: parent directory not present %s\n", parentDir) + return ErrDirectoryNotPresent } - var parentDirInode *Inode - err = json.Unmarshal(parentData, &parentDirInode) - if err != nil { // skipcq: TCV-001 - return err - } + parentHash := utils.HashString(parentDir) if isFile { itemToDelete = "_F_" + itemToDelete @@ -117,7 +105,7 @@ func (d *Directory) RemoveEntryFromDir(parentDir, podPassword, itemToDelete stri parentDirInode.FileOrDirNames = fileNames parentDirInode.Meta.ModificationTime = time.Now().Unix() - parentData, err = json.Marshal(parentDirInode) + parentData, err := json.Marshal(parentDirInode) if err != nil { // skipcq: TCV-001 return err } diff --git a/pkg/dir/rename.go b/pkg/dir/rename.go index 8c5a4e69..0a5a5721 100644 --- a/pkg/dir/rename.go +++ b/pkg/dir/rename.go @@ -36,15 +36,15 @@ func (d *Directory) RenameDir(dirNameWithPath, newDirNameWithPath, podPassword s } // check if directory exists - if d.GetDirFromDirectoryMap(dirNameWithPath) == nil { // skipcq: TCV-001 + if d.GetInode(podPassword, dirNameWithPath) == nil { // skipcq: TCV-001 return ErrDirectoryNotPresent } // check if parent directory exists - if d.GetDirFromDirectoryMap(parentPath) == nil { // skipcq: TCV-001 + if d.GetInode(podPassword, parentPath) == nil { // skipcq: TCV-001 return ErrDirectoryNotPresent } - if d.GetDirFromDirectoryMap(newDirNameWithPath) != nil { + if d.GetInode(podPassword, newDirNameWithPath) != nil { return ErrDirectoryAlreadyPresent } diff --git a/pkg/dir/rename_test.go b/pkg/dir/rename_test.go index 174454e3..5789094c 100644 --- a/pkg/dir/rename_test.go +++ b/pkg/dir/rename_test.go @@ -48,7 +48,7 @@ func TestRenameDirectory(t *testing.T) { if err != nil { t.Fatal(err) } - err := dirObject.MkDir("/", podPassword) + err := dirObject.MkDir("/", podPassword, 0) if !errors.Is(err, dir.ErrInvalidDirectoryName) { t.Fatal("invalid dir name") } @@ -56,40 +56,40 @@ func TestRenameDirectory(t *testing.T) { if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/"+longDirName, podPassword) + err = dirObject.MkDir("/"+longDirName, podPassword, 0) if !errors.Is(err, dir.ErrTooLongDirectoryName) { t.Fatal("dir name too long") } // create some dir and files - err = dirObject.MkDir("/parentDir", podPassword) + err = dirObject.MkDir("/parentDir", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/parentDir", podPassword) + err = dirObject.MkDir("/parentDir", podPassword, 0) if !errors.Is(err, dir.ErrDirectoryAlreadyPresent) { t.Fatal("dir already present") } // populate the directory with few directory and files - err = dirObject.MkDir("/parentDir/subDir1", podPassword) + err = dirObject.MkDir("/parentDir/subDir1", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/parentDir/subDir2", podPassword) + err = dirObject.MkDir("/parentDir/subDir2", podPassword, 0) if err != nil { t.Fatal(err) } r := new(bytes.Buffer) - err = fileObject.Upload(r, "file1", 0, 100, "/parentDir", "", podPassword) + err = fileObject.Upload(r, "file1", 0, 100, 0, "/parentDir", "", podPassword) if err != nil { t.Fatal(err) } - err = fileObject.Upload(r, "file2", 0, 100, "/parentDir", "", podPassword) + err = fileObject.Upload(r, "file2", 0, 100, 0, "/parentDir", "", podPassword) if err != nil { t.Fatal(err) } - err = fileObject.Upload(r, "file2", 0, 100, "/parentDir/subDir2", "", podPassword) + err = fileObject.Upload(r, "file2", 0, 100, 0, "/parentDir/subDir2", "", podPassword) if err != nil { t.Fatal(err) } @@ -119,7 +119,7 @@ func TestRenameDirectory(t *testing.T) { t.Fatal("rename failed for parentDir") } - err = dirObject.MkDir("/parent", podPassword) + err = dirObject.MkDir("/parent", podPassword, 0) if err != nil { t.Fatal(err) } @@ -191,7 +191,7 @@ func TestRenameDirectory(t *testing.T) { if err != nil { t.Fatal(err) } - err := dirObject.MkDir("/", podPassword) + err := dirObject.MkDir("/", podPassword, 0) if !errors.Is(err, dir.ErrInvalidDirectoryName) { t.Fatal("invalid dir name") } @@ -199,37 +199,37 @@ func TestRenameDirectory(t *testing.T) { if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/"+longDirName, podPassword) + err = dirObject.MkDir("/"+longDirName, podPassword, 0) if !errors.Is(err, dir.ErrTooLongDirectoryName) { t.Fatal("dir name too long") } // create some dir and files - err = dirObject.MkDir("/parentDir", podPassword) + err = dirObject.MkDir("/parentDir", podPassword, 0) if err != nil { t.Fatal(err) } // populate the directory with few directory and files - err = dirObject.MkDir("/parentDir/subDir1", podPassword) + err = dirObject.MkDir("/parentDir/subDir1", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/parentDir/subDir1/subDir11", podPassword) + err = dirObject.MkDir("/parentDir/subDir1/subDir11", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/parentDir/subDir1/subDir11/sub111", podPassword) + err = dirObject.MkDir("/parentDir/subDir1/subDir11/sub111", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/parentDir/subDir2", podPassword) + err = dirObject.MkDir("/parentDir/subDir2", podPassword, 0) if err != nil { t.Fatal(err) } r := new(bytes.Buffer) - err = fileObject.Upload(r, "file1", 0, 100, "/parentDir/subDir1/subDir11/sub111", "", podPassword) + err = fileObject.Upload(r, "file1", 0, 100, 0, "/parentDir/subDir1/subDir11/sub111", "", podPassword) if err != nil { t.Fatal(err) } diff --git a/pkg/dir/rmdir.go b/pkg/dir/rmdir.go index 39365774..ecf3cb54 100644 --- a/pkg/dir/rmdir.go +++ b/pkg/dir/rmdir.go @@ -46,11 +46,12 @@ func (d *Directory) RmDir(directoryNameWithPath, podPassword string) error { } else { totalPath = utils.CombinePathAndFile(parentPath, dirToDelete) } - if d.GetDirFromDirectoryMap(totalPath) == nil { + // recursive delete + dirInode := d.GetInode(podPassword, totalPath) + if dirInode == nil { return ErrDirectoryNotPresent } - // recursive delete - dirInode := d.GetDirFromDirectoryMap(totalPath) + if dirInode.FileOrDirNames != nil && len(dirInode.FileOrDirNames) > 0 { for _, fileOrDirName := range dirInode.FileOrDirNames { if strings.HasPrefix(fileOrDirName, "_F_") { diff --git a/pkg/dir/rmdir_test.go b/pkg/dir/rmdir_test.go index b1f517e9..1eb2482e 100644 --- a/pkg/dir/rmdir_test.go +++ b/pkg/dir/rmdir_test.go @@ -69,7 +69,7 @@ func TestRmdir(t *testing.T) { } // create a new dir - err := dirObject.MkDir("/dirToRemove", podPassword) + err := dirObject.MkDir("/dirToRemove", podPassword, 0) if err != nil { t.Fatal(err) } @@ -119,17 +119,17 @@ func TestRmdir(t *testing.T) { } // create a new dir - err := dirObject.MkDir("/dirToRemove1", podPassword) + err := dirObject.MkDir("/dirToRemove1", podPassword, 0) if err != nil { t.Fatal(err) } // create a new dir - err = dirObject.MkDir("/dirToRemove1/dirToRemove2", podPassword) + err = dirObject.MkDir("/dirToRemove1/dirToRemove2", podPassword, 0) if err != nil { t.Fatal(err) } // create a new dir - err = dirObject.MkDir("/dirToRemove1/dirToRemove2/dirToRemove", podPassword) + err = dirObject.MkDir("/dirToRemove1/dirToRemove2/dirToRemove", podPassword, 0) if err != nil { t.Fatal(err) } @@ -198,17 +198,17 @@ func TestRmRootDirByPath(t *testing.T) { } // create a new dir - err := dirObject.MkDir("/dirToRemove1", podPassword) + err := dirObject.MkDir("/dirToRemove1", podPassword, 0) if err != nil { t.Fatal(err) } // create a new dir - err = dirObject.MkDir("/dirToRemove1/dirToRemove2", podPassword) + err = dirObject.MkDir("/dirToRemove1/dirToRemove2", podPassword, 0) if err != nil { t.Fatal(err) } // create a new dir - err = dirObject.MkDir("/dirToRemove1/dirToRemove2/dirToRemove", podPassword) + err = dirObject.MkDir("/dirToRemove1/dirToRemove2/dirToRemove", podPassword, 0) if err != nil { t.Fatal(err) } @@ -290,17 +290,17 @@ func TestRmRootDir(t *testing.T) { } // create a new dir - err := dirObject.MkDir("/dirToRemove1", podPassword) + err := dirObject.MkDir("/dirToRemove1", podPassword, 0) if err != nil { t.Fatal(err) } // create a new dir - err = dirObject.MkDir("/dirToRemove1/dirToRemove2", podPassword) + err = dirObject.MkDir("/dirToRemove1/dirToRemove2", podPassword, 0) if err != nil { t.Fatal(err) } // create a new dir - err = dirObject.MkDir("/dirToRemove1/dirToRemove2/dirToRemove", podPassword) + err = dirObject.MkDir("/dirToRemove1/dirToRemove2/dirToRemove", podPassword, 0) if err != nil { t.Fatal(err) } diff --git a/pkg/dir/stat_test.go b/pkg/dir/stat_test.go index 1bf691fc..c20a772c 100644 --- a/pkg/dir/stat_test.go +++ b/pkg/dir/stat_test.go @@ -68,15 +68,15 @@ func TestStat(t *testing.T) { } // populate the directory with few directory and files - err := dirObject.MkDir("/dirToStat", podPassword) + err := dirObject.MkDir("/dirToStat", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/dirToStat/subDir1", podPassword) + err = dirObject.MkDir("/dirToStat/subDir1", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/dirToStat/subDir2", podPassword) + err = dirObject.MkDir("/dirToStat/subDir2", podPassword, 0) if err != nil { t.Fatal(err) } diff --git a/pkg/dir/sync.go b/pkg/dir/sync.go index eccc6118..dad0186e 100644 --- a/pkg/dir/sync.go +++ b/pkg/dir/sync.go @@ -85,7 +85,7 @@ func (d *Directory) SyncDirectoryAsync(ctx context.Context, dirNameWithPath, pod syncTask := newSyncTask(d, filePath, podPassword, wg) _, err = d.syncManager.Go(syncTask) if err != nil { // skipcq: TCV-001 - return err + wg.Done() } } else if strings.HasPrefix(fileOrDirName, "_D_") { dirName := strings.TrimPrefix(fileOrDirName, "_D_") diff --git a/pkg/dir/sync_test.go b/pkg/dir/sync_test.go index 10ad3ae3..6a0b24b2 100644 --- a/pkg/dir/sync_test.go +++ b/pkg/dir/sync_test.go @@ -70,15 +70,15 @@ func TestSync(t *testing.T) { } // populate the directory with few directory and files - err := dirObject.MkDir("/dirToStat", podPassword) + err := dirObject.MkDir("/dirToStat", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/dirToStat/subDir1", podPassword) + err = dirObject.MkDir("/dirToStat/subDir1", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/dirToStat/subDir2", podPassword) + err = dirObject.MkDir("/dirToStat/subDir2", podPassword, 0) if err != nil { t.Fatal(err) } diff --git a/pkg/ensm/ensm.go b/pkg/ensm/ensm.go index 7ee94cfd..84605f4d 100644 --- a/pkg/ensm/ensm.go +++ b/pkg/ensm/ensm.go @@ -15,4 +15,6 @@ type ENSManager interface { SetResolver(username string, owner common.Address, key *ecdsa.PrivateKey) (string, error) SetAll(username string, owner common.Address, key *ecdsa.PrivateKey) error GetInfo(username string) (*ecdsa.PublicKey, string, error) + GetInfoFromNameHash(node [32]byte) (common.Address, *ecdsa.PublicKey, string, error) + GetNameHash(username string) ([32]byte, error) } diff --git a/pkg/ensm/eth/eth.go b/pkg/ensm/eth/eth.go index f6ccd740..d1ab0535 100644 --- a/pkg/ensm/eth/eth.go +++ b/pkg/ensm/eth/eth.go @@ -40,7 +40,7 @@ var ( // Client is used to manage ENS type Client struct { eth *ethclient.Client - ensConfig *contracts.Config + ensConfig *contracts.ENSConfig ensRegistry *ens.ENSRegistry fdsRegistrar *fdsregistrar.FDSRegistrar publicResolver *publicresolver.PublicResolver @@ -49,7 +49,7 @@ type Client struct { } // New returns a new ENS manager Client -func New(ensConfig *contracts.Config, logger logging.Logger) (*Client, error) { +func New(ensConfig *contracts.ENSConfig, logger logging.Logger) (*Client, error) { eth, err := ethclient.Dial(ensConfig.ProviderBackend) if err != nil { return nil, fmt.Errorf("dial eth ensm: %w", err) @@ -205,11 +205,21 @@ func (c *Client) GetInfo(username string) (*ecdsa.PublicKey, string, error) { return nil, "", err } + _, pub, nameHashStr, err := c.GetInfoFromNameHash(node) + if err != nil { + return nil, "", err + } + + return pub, nameHashStr, nil +} + +// GetInfoFromNameHash returns the public key of the user from nameHash +func (c *Client) GetInfoFromNameHash(node [32]byte) (common.Address, *ecdsa.PublicKey, string, error) { opts := &bind.CallOpts{} info, err := c.publicResolver.GetAll(opts, node) if err != nil { c.logger.Error("public resolver get all failed : ", err) - return nil, "", err + return common.Address{}, nil, "", err } x := new(big.Int) x.SetBytes(info.X[:]) @@ -222,7 +232,11 @@ func (c *Client) GetInfo(username string) (*ecdsa.PublicKey, string, error) { pub.Curve = btcec.S256() nameHash := node[:] - return pub, utils.Encode(nameHash), nil + return info.Addr, pub, utils.Encode(nameHash), nil +} + +func (c *Client) GetNameHash(username string) ([32]byte, error) { + return goens.NameHash(username + "." + c.ensConfig.ProviderDomain) } func (c *Client) newTransactor(key *ecdsa.PrivateKey, account common.Address) (*bind.TransactOpts, error) { diff --git a/pkg/ensm/eth/mock/eth.go b/pkg/ensm/eth/mock/eth.go index 1242bfd3..72bc2a8e 100644 --- a/pkg/ensm/eth/mock/eth.go +++ b/pkg/ensm/eth/mock/eth.go @@ -6,6 +6,9 @@ import ( "math/big" "sync" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" + goens "github.com/wealdtech/go-ens/v3" + "github.com/btcsuite/btcd/btcec" "github.com/ethereum/go-ethereum/common" ) @@ -25,6 +28,40 @@ type NamespaceManager struct { storerMu sync.RWMutex } +func (c *NamespaceManager) GetInfoFromNameHash(node [32]byte) (common.Address, *ecdsa.PublicKey, string, error) { + c.storerMu.Lock() + defer c.storerMu.Unlock() + + for username, i := range c.publicResolver { + nh, err := goens.NameHash(username) + if err != nil { + return common.Address{}, nil, "", err + } + if nh == node { + addr := c.storer[username] + if addr == "" { + return common.Address{}, nil, "", fmt.Errorf("username not available") + } + x := new(big.Int) + x.SetBytes(i.X[:]) + + y := new(big.Int) + y.SetBytes(i.Y[:]) + pub := new(ecdsa.PublicKey) + pub.X = x + pub.Y = y + + pub.Curve = btcec.S256() + return common.HexToAddress(addr), pub, utils.Encode(nh[:]), nil + } + } + return common.Address{}, nil, "", fmt.Errorf("info not available") +} + +func (c *NamespaceManager) GetNameHash(username string) ([32]byte, error) { + return goens.NameHash(username) +} + // GetInfo returns the public key of the user func (c *NamespaceManager) GetInfo(username string) (*ecdsa.PublicKey, string, error) { c.storerMu.Lock() diff --git a/pkg/feed/api.go b/pkg/feed/api.go index c78a0a85..43f734f5 100644 --- a/pkg/feed/api.go +++ b/pkg/feed/api.go @@ -104,7 +104,6 @@ func (a *API) CreateFeed(topic []byte, user utils.Address, data []byte, encrypti return nil, err } } - // fill Feed and Epoc related details copy(req.ID.Topic[:], topic) req.ID.User = user @@ -119,13 +118,11 @@ func (a *API) CreateFeed(topic []byte, user utils.Address, data []byte, encrypti if err != nil { // skipcq: TCV-001 return nil, err } - // get the payload id BMT(span, payload) payloadId, err := a.handler.getPayloadId(encryptedData) if err != nil { // skipcq: TCV-001 return nil, err } - // create the signer and the content addressed chunk signer := crypto.NewDefaultSigner(a.accountInfo.GetPrivateKey()) ch, err := utils.NewChunkWithSpan(encryptedData) @@ -137,35 +134,26 @@ func (a *API) CreateFeed(topic []byte, user utils.Address, data []byte, encrypti if err != nil { // skipcq: TCV-001 return nil, err } - // generate the data to sign toSignBytes, err := toSignDigest(id, ch.Address().Bytes()) if err != nil { // skipcq: TCV-001 return nil, err } - // sign the chunk signature, err := signer.Sign(toSignBytes) if err != nil { // skipcq: TCV-001 return nil, err } - // set the address and the data for the soc chunk req.idAddr = sch.Address() req.binaryData = sch.Data() - // set signature and binary data fields _, err = a.handler.toChunkContent(&req, id, payloadId) if err != nil { // skipcq: TCV-001 return nil, err } // send the updated soc chunk to bee - address, err := a.handler.update(id, user.ToBytes(), signature, ch.Data()) - if err != nil { // skipcq: TCV-001 - return nil, err - } - - return address, nil + return a.handler.update(id, user.ToBytes(), signature, ch.Data()) } // CreateFeedFromTopic creates a soc with the topic as identifier @@ -302,7 +290,6 @@ func (a *API) UpdateFeed(topic []byte, user utils.Address, data []byte, encrypti return nil, err } } - ctx := context.Background() f := new(Feed) f.User = user @@ -315,19 +302,16 @@ func (a *API) UpdateFeed(topic []byte, user utils.Address, data []byte, encrypti } req.Time = uint64(time.Now().Unix()) req.data = encryptedData - // create the id, hash(topic, epoc) id, err := a.handler.getId(req.Topic, req.Time, req.Level) if err != nil { // skipcq: TCV-001 return nil, err } - // get the payload id BMT(span, payload) payloadId, err := a.handler.getPayloadId(encryptedData) if err != nil { // skipcq: TCV-001 return nil, err } - // create the signer and the content addressed chunk signer := crypto.NewDefaultSigner(a.accountInfo.GetPrivateKey()) ch, err := utils.NewChunkWithSpan(encryptedData) @@ -339,34 +323,25 @@ func (a *API) UpdateFeed(topic []byte, user utils.Address, data []byte, encrypti if err != nil { // skipcq: TCV-001 return nil, err } - // generate the data to sign toSignBytes, err := toSignDigest(id, ch.Address().Bytes()) if err != nil { // skipcq: TCV-001 return nil, err } - // sign the chunk signature, err := signer.Sign(toSignBytes) if err != nil { // skipcq: TCV-001 return nil, err } - // set the address and the data for the soc chunk req.idAddr = sch.Address() req.binaryData = sch.Data() - // set signature and binary data fields _, err = a.handler.toChunkContent(req, id, payloadId) if err != nil { // skipcq: TCV-001 return nil, err } - - address, err := a.handler.update(id, user.ToBytes(), signature, ch.Data()) - if err != nil { // skipcq: TCV-001 - return nil, err - } - return address, nil + return a.handler.update(id, user.ToBytes(), signature, ch.Data()) } // DeleteFeed deleted the feed by updating with no data inside the SOC chunk. diff --git a/pkg/file/IFile.go b/pkg/file/IFile.go index 5f0aebbb..53f5ab38 100644 --- a/pkg/file/IFile.go +++ b/pkg/file/IFile.go @@ -20,7 +20,7 @@ import "io" // IFile type IFile interface { - Upload(fd io.Reader, podFileName string, fileSize int64, blockSize uint32, podPath, compression, podPassword string) error + Upload(fd io.Reader, podFileName string, fileSize int64, blockSize, uint32 uint32, podPath, compression, podPassword string) error Download(podFileWithPath, podPassword string) (io.ReadCloser, uint64, error) ListFiles(files []string, podPassword string) ([]Entry, error) GetStats(podName, podFileWithPath, podPassword string) (*Stats, error) diff --git a/pkg/file/chmod.go b/pkg/file/chmod.go index d5169a10..c8def223 100644 --- a/pkg/file/chmod.go +++ b/pkg/file/chmod.go @@ -15,15 +15,18 @@ func (f *File) Chmod(podFileWithPath, podPassword string, mode uint32) error { } // check if file present totalFilePath := utils.CombinePathAndFile(podFileWithPath, "") - if !f.IsFileAlreadyPresent(totalFilePath) { - return ErrFileNotPresent + if !f.IsFileAlreadyPresent(podPassword, totalFilePath) { + return ErrFileNotFound } - meta := f.GetFromFileMap(totalFilePath) + meta := f.GetInode(podPassword, totalFilePath) if meta == nil { // skipcq: TCV-001 return ErrFileNotFound } + if meta.Mode == S_IFREG|mode { + return nil + } meta.Mode = S_IFREG | mode meta.AccessTime = time.Now().Unix() diff --git a/pkg/file/chmod_test.go b/pkg/file/chmod_test.go index 996f64db..808c2453 100644 --- a/pkg/file/chmod_test.go +++ b/pkg/file/chmod_test.go @@ -53,7 +53,7 @@ func TestChmod(t *testing.T) { assert.Equal(t, fmt.Sprintf("%o", file.S_IFREG|0600), fmt.Sprintf("%o", stats.Mode)) err = fileObject.Chmod("/dir1/file2", podPassword, 0777) - assert.Equal(t, err, file.ErrFileNotPresent) + assert.Equal(t, err, file.ErrFileNotFound) err = fileObject.Chmod("/dir1/file1", podPassword, 0777) require.NoError(t, err) diff --git a/pkg/file/download.go b/pkg/file/download.go index a3ff6d1f..0374e7d4 100644 --- a/pkg/file/download.go +++ b/pkg/file/download.go @@ -26,8 +26,6 @@ import ( ) var ( - // ErrFileNotPresent denotes file is not present - ErrFileNotPresent = errors.New("file not present") // ErrFileAlreadyPresent denotes file is present ErrFileAlreadyPresent = errors.New("file already present in the destination dir") @@ -50,11 +48,11 @@ func (f *File) Download(podFileWithPath, podPassword string) (io.ReadCloser, uin func (f *File) ReadSeeker(podFileWithPath, podPassword string) (io.ReadSeekCloser, uint64, error) { // check if file present totalFilePath := utils.CombinePathAndFile(podFileWithPath, "") - if !f.IsFileAlreadyPresent(totalFilePath) { - return nil, 0, ErrFileNotPresent + if !f.IsFileAlreadyPresent(podPassword, totalFilePath) { + return nil, 0, ErrFileNotFound } - meta := f.GetFromFileMap(totalFilePath) + meta := f.GetInode(podPassword, totalFilePath) if meta == nil { // skipcq: TCV-001 return nil, 0, ErrFileNotFound } diff --git a/pkg/file/download_test.go b/pkg/file/download_test.go index 0f772835..20dc0525 100644 --- a/pkg/file/download_test.go +++ b/pkg/file/download_test.go @@ -65,10 +65,10 @@ func TestDownload(t *testing.T) { // file existent check podFile := utils.CombinePathAndFile(filePath, fileName) - assert.Equal(t, fileObject.IsFileAlreadyPresent(podFile), false) + assert.Equal(t, fileObject.IsFileAlreadyPresent(podPassword, podFile), false) _, _, err = fileObject.Download(podFile, podPassword) - assert.Equal(t, err, file.ErrFileNotPresent) + assert.Equal(t, err, file.ErrFileNotFound) // upload a file content, err := uploadFile(t, fileObject, filePath, fileName, compression, podPassword, fileSize, blockSize) @@ -109,10 +109,10 @@ func TestDownload(t *testing.T) { // file existent check podFile := utils.CombinePathAndFile(filePath, fileName) - assert.Equal(t, fileObject.IsFileAlreadyPresent(podFile), false) + assert.Equal(t, fileObject.IsFileAlreadyPresent(podPassword, podFile), false) _, _, err = fileObject.Download(podFile, podPassword) - assert.Equal(t, err, file.ErrFileNotPresent) + assert.Equal(t, err, file.ErrFileNotFound) // upload a file content, err := uploadFile(t, fileObject, filePath, fileName, compression, podPassword, fileSize, blockSize) @@ -145,10 +145,10 @@ func TestDownload(t *testing.T) { // file existent check podFile := utils.CombinePathAndFile(filePath, fileName) - assert.Equal(t, fileObject.IsFileAlreadyPresent(podFile), false) + assert.Equal(t, fileObject.IsFileAlreadyPresent(podPassword, podFile), false) _, _, err = fileObject.Download(podFile, podPassword) - assert.Equal(t, err, file.ErrFileNotPresent) + assert.Equal(t, err, file.ErrFileNotFound) // upload a file content, err := uploadFile(t, fileObject, filePath, fileName, compression, podPassword, fileSize, blockSize) diff --git a/pkg/file/file.go b/pkg/file/file.go index 6eceff82..520ff9b1 100644 --- a/pkg/file/file.go +++ b/pkg/file/file.go @@ -88,17 +88,12 @@ func (f *File) GetFromFileMap(filePath string) *MetaData { } // IsFileAlreadyPresent checks if a file is present in the fileMap -func (f *File) IsFileAlreadyPresent(fileWithPath string) bool { - f.fileMu.Lock() - defer f.fileMu.Unlock() - if _, ok := f.fileMap[fileWithPath]; ok { - return true - } - return false +func (f *File) IsFileAlreadyPresent(podPassword, fileWithPath string) bool { + return f.GetInode(podPassword, fileWithPath) != nil } // RemoveAllFromFileMap resets the fileMap -func (f *File) RemoveAllFromFileMap() { +func (f *File) RemoveAllFromFileMap() { // skipcq: TCV-001 f.fileMu.Lock() defer f.fileMu.Unlock() f.fileMap = make(map[string]*MetaData) @@ -127,6 +122,30 @@ func (f *File) DeleteFromTagMap(filePath string) { // skipcq: TCV-001 f.tagMap.Delete(filePath) } +func (f *File) GetInode(podPassword, filePath string) *MetaData { // skipcq: TCV-001 + meta := f.GetFromFileMap(filePath) + if meta != nil { + return meta + } + topic := utils.HashString(filePath) + _, metaBytes, err := f.fd.GetFeedData(topic, f.userAddress, []byte(podPassword)) + if err != nil { + return nil + } + + if string(metaBytes) == utils.DeletedFeedMagicWord { + return nil + } + + err = json.Unmarshal(metaBytes, &meta) + if err != nil { // skipcq: TCV-001 + return nil + } + + f.AddToFileMap(filePath, meta) + return meta +} + type lsTask struct { f *File topic []byte diff --git a/pkg/file/meta.go b/pkg/file/meta.go index f59750e3..4fba3a1d 100644 --- a/pkg/file/meta.go +++ b/pkg/file/meta.go @@ -32,6 +32,7 @@ var ( //ErrDeletedFeed ErrDeletedFeed = errors.New("deleted feed") + ErrUnknownFeed = errors.New("unknown value in feed") ) // MetaData @@ -66,14 +67,11 @@ func (f *File) LoadFileMeta(fileNameWithPath, podPassword string) error { func (f *File) handleMeta(meta *MetaData, podPassword string) error { // check if meta is present. - totalPath := utils.CombinePathAndFile(meta.Path, meta.Name) - _, err := f.GetMetaFromFileName(totalPath, podPassword, f.userAddress) + err := f.uploadMeta(meta, podPassword) if err != nil { - if err != ErrDeletedFeed { - return f.uploadMeta(meta, podPassword) - } + return f.updateMeta(meta, podPassword) } - return f.updateMeta(meta, podPassword) + return nil } func (f *File) uploadMeta(meta *MetaData, podPassword string) error { @@ -87,11 +85,7 @@ func (f *File) uploadMeta(meta *MetaData, podPassword string) error { totalPath := utils.CombinePathAndFile(meta.Path, meta.Name) topic := utils.HashString(totalPath) _, err = f.fd.CreateFeed(topic, f.userAddress, fileMetaBytes, []byte(podPassword)) - if err != nil { // skipcq: TCV-001 - return err - } - - return nil + return err } func (f *File) deleteMeta(meta *MetaData, podPassword string) error { @@ -102,10 +96,7 @@ func (f *File) deleteMeta(meta *MetaData, podPassword string) error { if err != nil { // skipcq: TCV-001 return err } - err = f.fd.DeleteFeed(topic, f.userAddress) - if err != nil { - f.logger.Warningf("failed to remove file feed %s", totalPath) - } + return nil } @@ -158,13 +149,13 @@ func (f *File) BackupFromFileName(fileNameWithPath, podPassword string) (*MetaDa func (f *File) RenameFromFileName(fileNameWithPath, newFileNameWithPath, podPassword string) (*MetaData, error) { fileNameWithPath = filepath.ToSlash(fileNameWithPath) newFileNameWithPath = filepath.ToSlash(newFileNameWithPath) - p, err := f.GetMetaFromFileName(fileNameWithPath, podPassword, f.userAddress) - if err != nil { - return nil, err + p := f.GetInode(podPassword, fileNameWithPath) + if p == nil { + return nil, ErrFileNotFound } // remove old meta and from file map - err = f.deleteMeta(p, podPassword) + err := f.deleteMeta(p, podPassword) if err != nil { return nil, err } @@ -201,11 +192,10 @@ func (f *File) GetMetaFromFileName(fileNameWithPath, podPassword string, userAdd f.logger.Errorf("found deleted feed for %s\n", fileNameWithPath) return nil, ErrDeletedFeed } - var meta *MetaData err = json.Unmarshal(metaBytes, &meta) if err != nil { // skipcq: TCV-001 - return nil, err + return nil, ErrUnknownFeed } return meta, nil diff --git a/pkg/file/mock/mock_file.go b/pkg/file/mock/mock_file.go index 48ba166b..520c3831 100644 --- a/pkg/file/mock/mock_file.go +++ b/pkg/file/mock/mock_file.go @@ -32,7 +32,7 @@ func NewMockFile() *File { } // Upload -func (*File) Upload(_ io.Reader, _ string, _ int64, _ uint32, _, _, _ string) error { +func (*File) Upload(_ io.Reader, _ string, _ int64, _, _ uint32, _, _, _ string) error { return nil } diff --git a/pkg/file/reader.go b/pkg/file/reader.go index 54bca979..30969e4d 100644 --- a/pkg/file/reader.go +++ b/pkg/file/reader.go @@ -20,7 +20,6 @@ import ( "bytes" "encoding/json" "errors" - "fmt" "io" "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" @@ -62,9 +61,9 @@ type Reader struct { // TODO test // skipcq: TCV-001 func (f *File) OpenFileForIndex(podFile, podPassword string) (*Reader, error) { - meta := f.GetFromFileMap(podFile) + meta := f.GetInode(podPassword, podFile) if meta == nil { - return nil, fmt.Errorf("file not found in dfs") + return nil, ErrFileNotFound } encryptedFileInodeBytes, _, err := f.getClient().DownloadBlob(meta.InodeAddress) diff --git a/pkg/file/reader_test.go b/pkg/file/reader_test.go index 41f0f11c..3bedf445 100644 --- a/pkg/file/reader_test.go +++ b/pkg/file/reader_test.go @@ -329,7 +329,7 @@ func createFile(t *testing.T, fileSize uint64, blockSize uint32, compression str buf = compressedData } - addr, err := mockClient.UploadBlob(buf, 0, true, true) + addr, err := mockClient.UploadBlob(buf, 0, true) if err != nil { t.Fatal(err) } @@ -453,7 +453,7 @@ func createFileWithNewlines(t *testing.T, fileSize uint64, blockSize uint32, com buf = compressedData } - addr, err := mockClient.UploadBlob(buf, 0, true, true) + addr, err := mockClient.UploadBlob(buf, 0, true) if err != nil { t.Fatal(err) } diff --git a/pkg/file/rename_test.go b/pkg/file/rename_test.go index 275bd31c..a28bd180 100644 --- a/pkg/file/rename_test.go +++ b/pkg/file/rename_test.go @@ -50,7 +50,7 @@ func TestRename(t *testing.T) { // file existent check podFile := utils.CombinePathAndFile(filePath, fileName) - if fileObject.IsFileAlreadyPresent(podFile) { + if fileObject.IsFileAlreadyPresent(podPassword, podFile) { t.Fatal("file should not be present") } _, _, err = fileObject.Download(podFile, podPassword) @@ -70,11 +70,16 @@ func TestRename(t *testing.T) { } // Download the file and read from reader - present := fileObject.IsFileAlreadyPresent(podFile) + present := fileObject.IsFileAlreadyPresent(podPassword, podFile) if present { t.Fatal("old name should not be present") } + present = fileObject.IsFileAlreadyPresent(podPassword, newPodFile) + if !present { + t.Fatal("new name should be present") + } + // Download the file and read from reader reader, rcvdSize, err := fileObject.Download(utils.CombinePathAndFile(filePath, newFileName), podPassword) if err != nil { @@ -114,18 +119,18 @@ func TestRename(t *testing.T) { } // populate the directory with few directory and files - err = dirObject.MkDir(filePath, podPassword) + err = dirObject.MkDir(filePath, podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir(newFilePath, podPassword) + err = dirObject.MkDir(newFilePath, podPassword, 0) if err != nil { t.Fatal(err) } // file existent check podFile := utils.CombinePathAndFile(filePath, fileName) - if fileObject.IsFileAlreadyPresent(podFile) { + if fileObject.IsFileAlreadyPresent(podPassword, podFile) { t.Fatal("file should not be present") } @@ -135,7 +140,7 @@ func TestRename(t *testing.T) { t.Fatal(err) } newPodFile := utils.CombinePathAndFile(newFilePath, fileName) - if fileObject.IsFileAlreadyPresent(newPodFile) { + if fileObject.IsFileAlreadyPresent(podPassword, newPodFile) { t.Fatal("file should not be present") } _, err = fileObject.RenameFromFileName(podFile, newPodFile, podPassword) @@ -144,12 +149,12 @@ func TestRename(t *testing.T) { } // Download the file and read from reader - present := fileObject.IsFileAlreadyPresent(podFile) + present := fileObject.IsFileAlreadyPresent(podPassword, podFile) if present { t.Fatal("old name should not be present") } - present = fileObject.IsFileAlreadyPresent(newPodFile) + present = fileObject.IsFileAlreadyPresent(podPassword, newPodFile) if !present { t.Fatal("new name should be present") } diff --git a/pkg/file/rm.go b/pkg/file/rm.go index 61fa39ad..b10e1e6b 100644 --- a/pkg/file/rm.go +++ b/pkg/file/rm.go @@ -18,7 +18,6 @@ package file import ( "encoding/json" - "errors" "fmt" "net/http" @@ -29,12 +28,9 @@ import ( // RmFile deletes all the blocks of a file, and it related metadata from the Swarm network. func (f *File) RmFile(podFileWithPath, podPassword string) error { totalFilePath := utils.CombinePathAndFile(podFileWithPath, "") - meta, err := f.GetMetaFromFileName(totalFilePath, podPassword, f.userAddress) - if errors.Is(err, ErrDeletedFeed) { // skipcq: TCV-001 - return nil - } - if err != nil { - return err + meta := f.GetInode(podPassword, totalFilePath) + if meta == nil { + return ErrFileNotFound } fileInodeBytes, respCode, err := f.client.DownloadBlob(meta.InodeAddress) if err != nil { // skipcq: TCV-001 diff --git a/pkg/file/rm_test.go b/pkg/file/rm_test.go index fdfc9fe7..aad4cddf 100644 --- a/pkg/file/rm_test.go +++ b/pkg/file/rm_test.go @@ -59,7 +59,7 @@ func TestRemoveFile(t *testing.T) { fileObject := file.NewFile("pod1", mockClient, fd, user, tm, logger) // remove file2 err = fileObject.RmFile("/dir1/file2", podPassword) - require.Equal(t, err.Error(), "feed does not exist or was not updated yet") + require.Equal(t, err.Error(), file.ErrFileNotFound.Error()) file1, _ := utils.GetRandString(12) file2, _ := utils.GetRandString(12) @@ -75,13 +75,13 @@ func TestRemoveFile(t *testing.T) { require.NoError(t, err) // validate file deletion - meta := fileObject.GetFromFileMap(utils.CombinePathAndFile("/dir1", file2)) + meta := fileObject.GetInode(podPassword, utils.CombinePathAndFile("/dir1", file2)) if meta != nil { t.Fatalf("file is not removed") } // check if other file is present - meta = fileObject.GetFromFileMap(utils.CombinePathAndFile("/dir1", file1)) + meta = fileObject.GetInode(podPassword, utils.CombinePathAndFile("/dir1", file1)) if meta == nil { t.Fatalf("file is not present") } @@ -107,7 +107,7 @@ func TestRemoveFile(t *testing.T) { require.NoError(t, err) // validate file deletion - meta := fileObject.GetFromFileMap("/dir1/" + filename) + meta := fileObject.GetInode(podPassword, "/dir1/"+filename) if meta != nil { t.Fatalf("file is not removed") } diff --git a/pkg/file/stat.go b/pkg/file/stat.go index e10af93f..5e969099 100644 --- a/pkg/file/stat.go +++ b/pkg/file/stat.go @@ -17,63 +17,33 @@ limitations under the License. package file import ( - "encoding/hex" - "encoding/json" - "fmt" "strconv" ) // Stats type Stats struct { - PodName string `json:"podName"` - Mode uint32 `json:"mode"` - FilePath string `json:"filePath"` - FileName string `json:"fileName"` - FileSize string `json:"fileSize"` - BlockSize string `json:"blockSize"` - Compression string `json:"compression"` - ContentType string `json:"contentType"` - CreationTime string `json:"creationTime"` - ModificationTime string `json:"modificationTime"` - AccessTime string `json:"accessTime"` - Blocks []Blocks `json:"blocks"` -} - -// Blocks -type Blocks struct { - Reference string `json:"reference"` - Size string `json:"size"` - CompressedSize string `json:"compressedSize"` + PodName string `json:"podName"` + Mode uint32 `json:"mode"` + FilePath string `json:"filePath"` + FileName string `json:"fileName"` + FileSize string `json:"fileSize"` + BlockSize string `json:"blockSize"` + Compression string `json:"compression"` + ContentType string `json:"contentType"` + CreationTime string `json:"creationTime"` + ModificationTime string `json:"modificationTime"` + AccessTime string `json:"accessTime"` } // GetStats given a filename this function returns all the information about the file // including the block information. func (f *File) GetStats(podName, podFileWithPath, podPassword string) (*Stats, error) { - meta := f.GetFromFileMap(podFileWithPath) + meta := f.GetInode(podPassword, podFileWithPath) if meta == nil { // skipcq: TCV-001 - return nil, fmt.Errorf("file not found") - } - - fileInodeBytes, _, err := f.getClient().DownloadBlob(meta.InodeAddress) - if err != nil { // skipcq: TCV-001 - return nil, err + return nil, ErrFileNotFound } - var fileInode INode - err = json.Unmarshal(fileInodeBytes, &fileInode) - if err != nil { // skipcq: TCV-001 - return nil, err - } - - var fileBlocks []Blocks - for _, b := range fileInode.Blocks { - fb := Blocks{ - Reference: hex.EncodeToString(b.Reference.Bytes()), - Size: strconv.Itoa(int(b.Size)), - CompressedSize: strconv.Itoa(int(b.CompressedSize)), - } - fileBlocks = append(fileBlocks, fb) - } + f.AddToFileMap(podFileWithPath, meta) return &Stats{ PodName: podName, FilePath: meta.Path, @@ -86,6 +56,5 @@ func (f *File) GetStats(podName, podFileWithPath, podPassword string) (*Stats, e CreationTime: strconv.FormatInt(meta.CreationTime, 10), ModificationTime: strconv.FormatInt(meta.ModificationTime, 10), AccessTime: strconv.FormatInt(meta.AccessTime, 10), - Blocks: fileBlocks, }, nil } diff --git a/pkg/file/status.go b/pkg/file/status.go index af9f6143..706777a1 100644 --- a/pkg/file/status.go +++ b/pkg/file/status.go @@ -8,8 +8,8 @@ import ( func (f *File) Status(podFileWithPath, podPassword string) (int64, int64, int64, error) { // check if file present totalFilePath := utils.CombinePathAndFile(podFileWithPath, "") - if !f.IsFileAlreadyPresent(totalFilePath) { - return 0, 0, 0, ErrFileNotPresent + if !f.IsFileAlreadyPresent(podPassword, totalFilePath) { + return 0, 0, 0, ErrFileNotFound } tag := f.LoadFromTagMap(totalFilePath) diff --git a/pkg/file/upload.go b/pkg/file/upload.go index 1acaa30d..e9852874 100644 --- a/pkg/file/upload.go +++ b/pkg/file/upload.go @@ -50,7 +50,7 @@ var ( // Upload uploads a given blob of bytes as a file in the pod. It also splits the file into number of blocks. the // size of the block is provided during upload. This function also does compression of the blocks gzip/snappy if it is // requested during the upload. -func (f *File) Upload(fd io.Reader, podFileName string, fileSize int64, blockSize uint32, podPath, compression, podPassword string) error { +func (f *File) Upload(fd io.Reader, podFileName string, fileSize int64, blockSize, mode uint32, podPath, compression, podPassword string) error { podPath = filepath.ToSlash(podPath) // check compression gzip and blocksize // pgzip does not allow block size lower or equal to 163840, @@ -66,6 +66,9 @@ func (f *File) Upload(fd io.Reader, podFileName string, fileSize int64, blockSiz return err } + if mode == 0 { + mode = S_IFREG | defaultMode + } meta := MetaData{ Version: MetaVersion, Path: podPath, @@ -76,7 +79,7 @@ func (f *File) Upload(fd io.Reader, podFileName string, fileSize int64, blockSiz CreationTime: now, AccessTime: now, ModificationTime: now, - Mode: S_IFREG | defaultMode, + Mode: mode, } var totalLength uint64 @@ -147,7 +150,7 @@ func (f *File) Upload(fd io.Reader, podFileName string, fileSize int64, blockSiz } } - addr, uploadErr := f.client.UploadBlob(uploadData, tag, true, true) + addr, uploadErr := f.client.UploadBlob(uploadData, tag, true) if uploadErr != nil { mainErr = uploadErr return @@ -192,7 +195,7 @@ func (f *File) Upload(fd io.Reader, podFileName string, fileSize int64, blockSiz return err } - addr, err := f.client.UploadBlob(fileInodeData, 0, true, true) + addr, err := f.client.UploadBlob(fileInodeData, 0, true) if err != nil { // skipcq: TCV-001 return err } diff --git a/pkg/file/upload_test.go b/pkg/file/upload_test.go index 286026ab..ee45b377 100644 --- a/pkg/file/upload_test.go +++ b/pkg/file/upload_test.go @@ -72,7 +72,7 @@ func TestUpload(t *testing.T) { } // check for meta - meta := fileObject.GetFromFileMap(utils.CombinePathAndFile(filePath, fileName)) + meta := fileObject.GetInode(podPassword, utils.CombinePathAndFile(filePath, fileName)) if meta == nil { t.Fatalf("file not added in file map") } @@ -124,7 +124,7 @@ func TestUpload(t *testing.T) { } // check for meta - meta := fileObject.GetFromFileMap(utils.CombinePathAndFile(filepath.ToSlash(filePath), fileName)) + meta := fileObject.GetInode(podPassword, utils.CombinePathAndFile(filepath.ToSlash(filePath), fileName)) if meta == nil { t.Fatalf("file not added in file map") } @@ -159,7 +159,7 @@ func TestUpload(t *testing.T) { } // check for meta - meta := fileObject.GetFromFileMap(filepath.ToSlash(utils.CombinePathAndFile(filePath+fileName, ""))) + meta := fileObject.GetInode(podPassword, filepath.ToSlash(utils.CombinePathAndFile(filePath+fileName, ""))) if meta == nil { t.Fatalf("file not added in file map") } @@ -182,7 +182,7 @@ func TestUpload(t *testing.T) { t.Run("upload-small-file-at-root-with-prefix", func(t *testing.T) { podPassword, _ := utils.GetRandString(pod.PasswordLength) filePath := string(os.PathSeparator) - fileName := "file1" + fileName, _ := utils.GetRandString(20) compression := "" fileSize := int64(100) blockSize := uint32(10) @@ -193,7 +193,7 @@ func TestUpload(t *testing.T) { } // check for meta - meta := fileObject.GetFromFileMap(utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName))) + meta := fileObject.GetInode(podPassword, utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName))) if meta == nil { t.Fatalf("file not added in file map") } @@ -212,9 +212,11 @@ func TestUpload(t *testing.T) { t.Fatalf("invalid block size in meta") } - fileObject.RemoveAllFromFileMap() - - meta2 := fileObject.GetFromFileMap(utils.CombinePathAndFile(filePath, string(os.PathSeparator)+fileName)) + err = fileObject.RmFile(utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName)), podPassword) + if err != nil { + t.Fatal(err) + } + meta2 := fileObject.GetInode(podPassword, utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName))) if meta2 != nil { t.Fatal("meta2 should be nil") } @@ -223,7 +225,7 @@ func TestUpload(t *testing.T) { t.Run("upload-small-file-at-root-with-prefix-snappy", func(t *testing.T) { podPassword, _ := utils.GetRandString(pod.PasswordLength) filePath := string(os.PathSeparator) - fileName := "file2" + fileName, _ := utils.GetRandString(20) compression := "snappy" fileSize := int64(100) blockSize := uint32(10) @@ -234,7 +236,7 @@ func TestUpload(t *testing.T) { } // check for meta - meta := fileObject.GetFromFileMap(utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName))) + meta := fileObject.GetInode(podPassword, utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName))) if meta == nil { t.Fatalf("file not added in file map") } @@ -253,9 +255,12 @@ func TestUpload(t *testing.T) { t.Fatalf("invalid block size in meta") } - fileObject.RemoveAllFromFileMap() + err = fileObject.RmFile(utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName)), podPassword) + if err != nil { + t.Fatal(err) + } - meta2 := fileObject.GetFromFileMap(utils.CombinePathAndFile(filePath, string(os.PathSeparator)+fileName)) + meta2 := fileObject.GetInode(podPassword, utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName))) if meta2 != nil { t.Fatal("meta2 should be nil") } @@ -264,7 +269,7 @@ func TestUpload(t *testing.T) { t.Run("upload-small-file-at-root-with-prefix-gzip", func(t *testing.T) { podPassword, _ := utils.GetRandString(pod.PasswordLength) filePath := string(os.PathSeparator) - fileName := "file2" + fileName, _ := utils.GetRandString(20) compression := "gzip" fileSize := int64(100) blockSize := uint32(164000) @@ -282,7 +287,7 @@ func TestUpload(t *testing.T) { // check for meta fp := utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName)) - meta := fileObject.GetFromFileMap(fp) + meta := fileObject.GetInode(podPassword, fp) if meta == nil { t.Fatalf("file not added in file map") } @@ -309,9 +314,12 @@ func TestUpload(t *testing.T) { if err != nil { t.Fatal(err) } - fileObject.RemoveAllFromFileMap() + err = fileObject.RmFile(utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName)), podPassword) + if err != nil { + t.Fatal(err) + } - meta2 := fileObject.GetFromFileMap(fp) + meta2 := fileObject.GetInode(podPassword, fp) if meta2 != nil { t.Fatal("meta2 should be nil") } @@ -350,5 +358,5 @@ func uploadFile(t *testing.T, fileObject *file.File, filePath, fileName, compres } // upload the temp file - return content, fileObject.Upload(f1, fileName, fileSize, blockSize, filePath, compression, podPassword) + return content, fileObject.Upload(f1, fileName, fileSize, blockSize, 0, filePath, compression, podPassword) } diff --git a/pkg/file/writeAt.go b/pkg/file/writeAt.go index 70448c67..fc154318 100644 --- a/pkg/file/writeAt.go +++ b/pkg/file/writeAt.go @@ -15,12 +15,12 @@ import ( func (f *File) WriteAt(podFileWithPath, podPassword string, update io.Reader, offset uint64, truncate bool) (int, error) { // check file is present totalFilePath := utils.CombinePathAndFile(podFileWithPath, "") - if !f.IsFileAlreadyPresent(totalFilePath) { - return 0, ErrFileNotPresent + if !f.IsFileAlreadyPresent(podPassword, totalFilePath) { + return 0, ErrFileNotFound } // get file meta - meta := f.GetFromFileMap(totalFilePath) + meta := f.GetInode(podPassword, totalFilePath) if meta == nil { // skipcq: TCV-001 return 0, ErrFileNotFound } @@ -204,7 +204,7 @@ func (f *File) WriteAt(podFileWithPath, podPassword string, update io.Reader, of } } - addr, uploadErr := f.client.UploadBlob(uploadData, tag, true, true) + addr, uploadErr := f.client.UploadBlob(uploadData, tag, true) if uploadErr != nil { mainErr = uploadErr return @@ -249,7 +249,7 @@ func (f *File) WriteAt(podFileWithPath, podPassword string, update io.Reader, of return 0, err } - addr, err := f.client.UploadBlob(fileInodeData, 0, true, true) + addr, err := f.client.UploadBlob(fileInodeData, 0, true) if err != nil { // skipcq: TCV-001 return 0, err } diff --git a/pkg/file/writeAt_test.go b/pkg/file/writeAt_test.go index 345039bf..f2c507da 100644 --- a/pkg/file/writeAt_test.go +++ b/pkg/file/writeAt_test.go @@ -61,7 +61,7 @@ func TestWriteAt(t *testing.T) { rewrite := &bytes.Buffer{} rewrite.Write(update) _, err = fileObject.WriteAt(fp, podPassword, rewrite, offset, false) - if !errors.Is(file.ErrFileNotPresent, err) { + if !errors.Is(file.ErrFileNotFound, err) { t.Fatal("file should not be present") } }) @@ -81,7 +81,7 @@ func TestWriteAt(t *testing.T) { fp := utils.CombinePathAndFile(filepath.ToSlash(filePath+fileName), "") // check for meta - meta := fileObject.GetFromFileMap(fp) + meta := fileObject.GetInode(podPassword, fp) if meta == nil { t.Fatalf("file not added in file map") } @@ -156,9 +156,12 @@ func TestWriteAt(t *testing.T) { t.Fatal("content is different") } - fileObject.RemoveAllFromFileMap() + err = fileObject.RmFile(utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName)), podPassword) + if err != nil { + t.Fatal(err) + } - meta2 := fileObject.GetFromFileMap(fp) + meta2 := fileObject.GetInode(podPassword, fp) if meta2 != nil { t.Fatal("meta2 should be nil") } @@ -179,7 +182,7 @@ func TestWriteAt(t *testing.T) { fp := utils.CombinePathAndFile(filepath.ToSlash(filePath+fileName), "") // check for meta - meta := fileObject.GetFromFileMap(fp) + meta := fileObject.GetInode(podPassword, fp) if meta == nil { t.Fatalf("file not added in file map") } @@ -279,14 +282,15 @@ func TestWriteAt(t *testing.T) { t.Fatal("content is different") } - fileObject.RemoveAllFromFileMap() + err = fileObject.RmFile(utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName)), podPassword) + if err != nil { + t.Fatal(err) + } - meta2 := fileObject.GetFromFileMap(fp) + meta2 := fileObject.GetInode(podPassword, fp) if meta2 != nil { t.Fatal("meta2 should be nil") } - - fileObject.RemoveAllFromFileMap() }) t.Run("upload-update-truncate-known-very-small-file", func(t *testing.T) { @@ -304,7 +308,7 @@ func TestWriteAt(t *testing.T) { // check for meta fp := utils.CombinePathAndFile(filepath.ToSlash(filePath+fileName), "") - meta := fileObject.GetFromFileMap(fp) + meta := fileObject.GetInode(podPassword, fp) if meta == nil { t.Fatalf("file not added in file map") } @@ -355,9 +359,12 @@ func TestWriteAt(t *testing.T) { t.Fatal("content is different") } - fileObject.RemoveAllFromFileMap() + err = fileObject.RmFile(utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName)), podPassword) + if err != nil { + t.Fatal(err) + } - meta2 := fileObject.GetFromFileMap(fp) + meta2 := fileObject.GetInode(podPassword, fp) if meta2 != nil { t.Fatal("meta2 should be nil") } @@ -377,7 +384,7 @@ func TestWriteAt(t *testing.T) { // check for meta fp := utils.CombinePathAndFile(filepath.ToSlash(filePath), fileName) - meta := fileObject.GetFromFileMap(fp) + meta := fileObject.GetInode(podPassword, fp) if meta == nil { t.Fatalf("file not added in file map") } @@ -435,9 +442,12 @@ func TestWriteAt(t *testing.T) { if !bytes.Equal(updatedContent, rcvdBuffer.Bytes()) { t.Fatal("content is different") } - fileObject.RemoveAllFromFileMap() + err = fileObject.RmFile(utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName)), podPassword) + if err != nil { + t.Fatal(err) + } - meta2 := fileObject.GetFromFileMap(fp) + meta2 := fileObject.GetInode(podPassword, fp) if meta2 != nil { t.Fatal("meta2 should be nil") } @@ -457,7 +467,7 @@ func TestWriteAt(t *testing.T) { // check for meta fp := utils.CombinePathAndFile(filepath.ToSlash(filePath), fileName) - meta := fileObject.GetFromFileMap(fp) + meta := fileObject.GetInode(podPassword, fp) if meta == nil { t.Fatalf("file not added in file map") } @@ -511,9 +521,12 @@ func TestWriteAt(t *testing.T) { t.Fatal("content is different") } - fileObject.RemoveAllFromFileMap() + err = fileObject.RmFile(utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName)), podPassword) + if err != nil { + t.Fatal(err) + } - meta2 := fileObject.GetFromFileMap(fp) + meta2 := fileObject.GetInode(podPassword, fp) if meta2 != nil { t.Fatal("meta2 should be nil") } @@ -537,7 +550,7 @@ func TestWriteAt(t *testing.T) { // check for meta fp := utils.CombinePathAndFile(filepath.ToSlash(filePath), fileName) - meta := fileObject.GetFromFileMap(fp) + meta := fileObject.GetInode(podPassword, fp) if meta == nil { t.Fatalf("file not added in file map") } @@ -590,9 +603,12 @@ func TestWriteAt(t *testing.T) { t.Fatal("content is different ") } - fileObject.RemoveAllFromFileMap() + err = fileObject.RmFile(utils.CombinePathAndFile(filepath.ToSlash(filePath), filepath.ToSlash(string(os.PathSeparator)+fileName)), podPassword) + if err != nil { + t.Fatal(err) + } - meta2 := fileObject.GetFromFileMap(fp) + meta2 := fileObject.GetInode(podPassword, fp) if meta2 != nil { t.Fatal("meta2 should be nil") } @@ -607,5 +623,5 @@ func uploadFileKnownContent(t *testing.T, fileObject *file.File, filePath, fileN t.Fatal(err) } // upload the temp file - return content, fileObject.Upload(f1, fileName, int64(len(content)), blockSize, filePath, compression, podPassword) + return content, fileObject.Upload(f1, fileName, int64(len(content)), blockSize, 0, filePath, compression, podPassword) } diff --git a/pkg/pod/close.go b/pkg/pod/close.go index 2a9077d1..e341cf25 100644 --- a/pkg/pod/close.go +++ b/pkg/pod/close.go @@ -19,10 +19,6 @@ package pod // ClosePod closed an already opened pod and removes its information from directory and file // data structures. func (p *Pod) ClosePod(podName string) error { - if !p.IsPodOpened(podName) { - return ErrPodNotOpened - } - podInfo, _, err := p.GetPodInfoFromPodMap(podName) if err != nil { // skipcq: TCV-001 return err diff --git a/pkg/pod/del.go b/pkg/pod/del.go index 64824edb..7cbe06fe 100644 --- a/pkg/pod/del.go +++ b/pkg/pod/del.go @@ -40,7 +40,7 @@ func (p *Pod) DeleteOwnPod(podName string) error { } // delete tables - podInfo, _, err := p.GetPodInfoFromPodMap(podName) + podInfo, _, err := p.GetPodInfo(podName) if err != nil { return err } diff --git a/pkg/pod/fork.go b/pkg/pod/fork.go index 002bb0eb..abc51f39 100644 --- a/pkg/pod/fork.go +++ b/pkg/pod/fork.go @@ -19,11 +19,7 @@ func (p *Pod) PodFork(podName, forkName string) error { return err } - if !p.IsPodOpened(podName) { - return ErrPodNotOpened - } - - podInfo, _, err := p.GetPodInfoFromPodMap(podName) + podInfo, _, err := p.GetPodInfo(podName) if err != nil { // skipcq: TCV-001 return err } @@ -33,16 +29,16 @@ func (p *Pod) PodFork(podName, forkName string) error { return err } - if !p.IsPodOpened(forkName) { - return ErrPodNotOpened - } - - forkInfo, _, err := p.GetPodInfoFromPodMap(forkName) + forkInfo, _, err := p.GetPodInfo(forkName) if err != nil { // skipcq: TCV-001 return err } - rootInode := podInfo.GetDirectory().GetDirFromDirectoryMap("/") + directory := podInfo.GetDirectory() + rootInode := directory.GetInode(podInfo.GetPodPassword(), "/") + if rootInode == nil { + return fmt.Errorf("root inode not found") + } return cloneFolder(podInfo, forkInfo, "/", rootInode) } @@ -96,11 +92,7 @@ func (p *Pod) forkPod(podInfo *Info, forkName string) error { return err } - if !p.IsPodOpened(forkName) { - return ErrPodNotOpened - } - - forkInfo, _, err := p.GetPodInfoFromPodMap(forkName) + forkInfo, _, err := p.GetPodInfo(forkName) if err != nil { // skipcq: TCV-001 return err } @@ -115,14 +107,13 @@ func cloneFolder(source, dst *Info, dirNameWithPath string, dirInode *d.Inode) e if strings.HasPrefix(fileOrDirName, "_F_") { fileName := strings.TrimPrefix(fileOrDirName, "_F_") filePath := utils.CombinePathAndFile(dirNameWithPath, fileName) - meta := source.GetFile().GetFromFileMap(filePath) - + meta := source.GetFile().GetInode(source.GetPodPassword(), filePath) r, _, err := source.GetFile().Download(filePath, source.GetPodPassword()) if err != nil { // skipcq: TCV-001 return err } - err = dst.GetFile().Upload(r, meta.Name, int64(meta.Size), meta.BlockSize, meta.Path, meta.Compression, dst.GetPodPassword()) + err = dst.GetFile().Upload(r, meta.Name, int64(meta.Size), meta.BlockSize, 0, meta.Path, meta.Compression, dst.GetPodPassword()) if err != nil { // skipcq: TCV-001 return err } @@ -134,8 +125,8 @@ func cloneFolder(source, dst *Info, dirNameWithPath string, dirInode *d.Inode) e } else if strings.HasPrefix(fileOrDirName, "_D_") { dirName := strings.TrimPrefix(fileOrDirName, "_D_") path := utils.CombinePathAndFile(dirNameWithPath, dirName) - iNode := source.GetDirectory().GetDirFromDirectoryMap(path) - err := dst.GetDirectory().MkDir(path, dst.GetPodPassword()) + iNode := source.GetDirectory().GetInode(source.GetPodPassword(), path) + err := dst.GetDirectory().MkDir(path, dst.GetPodPassword(), 0) if err != nil { // skipcq: TCV-001 return err } diff --git a/pkg/pod/new.go b/pkg/pod/new.go index 1a31cc66..cbc90c83 100644 --- a/pkg/pod/new.go +++ b/pkg/pod/new.go @@ -148,6 +148,13 @@ func (p *Pod) CreatePod(podName, addressString, podPassword string) (*Info, erro docStore: docStore, } p.addPodToPodMap(podName, podInfo) + if addressString == "" { + // create the root directory + err = podInfo.GetDirectory().MkRootDir(podInfo.GetPodName(), podPassword, podInfo.GetPodAddress(), podInfo.GetFeed()) + if err != nil { + return nil, err + } + } return podInfo, nil } diff --git a/pkg/pod/open.go b/pkg/pod/open.go index d80feaba..0cec5aef 100644 --- a/pkg/pod/open.go +++ b/pkg/pod/open.go @@ -55,7 +55,7 @@ func (p *Pod) OpenPod(podName string) (*Info, error) { ) if sharedPodType { var addressString string - addressString, podPassword = p.getAddressPassword(podList, podName) + addressString, podPassword = p.getSharedAddressPassword(podList, podName) if addressString == "" { // skipcq: TCV-001 return nil, fmt.Errorf("shared pod does not exist") } @@ -107,12 +107,47 @@ func (p *Pod) OpenPod(podName string) (*Info, error) { } p.addPodToPodMap(podName, podInfo) + if !sharedPodType { + err = podInfo.GetDirectory().AddRootDir(podInfo.GetPodName(), podInfo.GetPodPassword(), podInfo.GetPodAddress(), podInfo.GetFeed()) + if err != nil { + return nil, err + } + } + + return podInfo, nil +} + +func (p *Pod) OpenFromShareInfo(si *ShareInfo) (*Info, error) { + accountInfo := p.acc.GetEmptyAccountInfo() + address := utils.HexToAddress(si.Address) + accountInfo.SetAddress(address) + + fd := feed.New(accountInfo, p.client, p.logger) + file := f.NewFile(si.PodName, p.client, fd, accountInfo.GetAddress(), p.tm, p.logger) + dir := d.NewDirectory(si.PodName, p.client, fd, accountInfo.GetAddress(), file, p.tm, p.logger) + + kvStore := c.NewKeyValueStore(si.PodName, fd, accountInfo, address, p.client, p.logger) + docStore := c.NewDocumentStore(si.PodName, fd, accountInfo, address, file, p.tm, p.client, p.logger) + + podInfo := &Info{ + podName: si.PodName, + podPassword: si.Password, + userAddress: address, + accountInfo: accountInfo, + feed: fd, + dir: dir, + file: file, + kvStore: kvStore, + docStore: docStore, + } + p.addPodToPodMap(si.PodName, podInfo) // sync the pod's files and directories - err = p.SyncPod(podName) + err := p.SyncPod(si.PodName) if err != nil && err != d.ErrResourceDeleted { // skipcq: TCV-001 return nil, err } + return podInfo, nil } @@ -145,7 +180,7 @@ func (p *Pod) OpenPodAsync(ctx context.Context, podName string) (*Info, error) { ) if sharedPodType { var addressString string - addressString, podPassword = p.getAddressPassword(podList, podName) + addressString, podPassword = p.getSharedAddressPassword(podList, podName) if addressString == "" { // skipcq: TCV-001 return nil, fmt.Errorf("shared pod does not exist") } @@ -214,7 +249,7 @@ func (*Pod) getIndexPassword(podList *List, podName string) (int, string) { return -1, "" // skipcq: TCV-001 } -func (*Pod) getAddressPassword(podList *List, podName string) (string, string) { +func (*Pod) getSharedAddressPassword(podList *List, podName string) (string, string) { for _, pod := range podList.SharedPods { if pod.Name == podName { return pod.Address, pod.Password @@ -222,3 +257,13 @@ func (*Pod) getAddressPassword(podList *List, podName string) (string, string) { } return "", "" } + +func (p *Pod) getAddressPassword(podList *List, podName string) (string, string) { + for _, pod := range podList.Pods { + if pod.Name == podName { + addr := p.acc.GetAddress(pod.Index) + return addr.Hex(), pod.Password + } + } + return "", "" +} diff --git a/pkg/pod/pod.go b/pkg/pod/pod.go index 3f9f9567..f14c199c 100644 --- a/pkg/pod/pod.go +++ b/pkg/pod/pod.go @@ -20,6 +20,8 @@ import ( "fmt" "sync" + "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager" + "github.com/fairdatasociety/fairOS-dfs/pkg/account" "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" @@ -43,6 +45,7 @@ type Pod struct { podMu *sync.RWMutex logger logging.Logger tm taskmanager.TaskManagerGO + sm subscriptionManager.SubscriptionManager } // ListItem defines the structure for pod item @@ -67,7 +70,7 @@ type List struct { // NewPod creates the main pod object which has all the methods related to the pods. func NewPod(client blockstore.Client, feed *feed.API, account *account.Account, - m taskmanager.TaskManagerGO, logger logging.Logger) *Pod { + m taskmanager.TaskManagerGO, sm subscriptionManager.SubscriptionManager, logger logging.Logger) *Pod { return &Pod{ fd: feed, acc: account, @@ -76,6 +79,7 @@ func NewPod(client blockstore.Client, feed *feed.API, account *account.Account, podMu: &sync.RWMutex{}, logger: logger, tm: m, + sm: sm, } } @@ -110,3 +114,16 @@ func (p *Pod) GetFeed() *feed.API { func (p *Pod) GetAccount() *account.Account { return p.acc } + +// GetPodInfo +func (p *Pod) GetPodInfo(podName string) (*Info, string, error) { + pi, password, _ := p.GetPodInfoFromPodMap(podName) + if pi != nil { + return pi, password, nil + } + pi, err := p.OpenPod(podName) + if err != nil { + return nil, "", err + } + return pi, pi.GetPodPassword(), nil +} diff --git a/pkg/pod/sharing.go b/pkg/pod/sharing.go index a788db21..78122fa4 100644 --- a/pkg/pod/sharing.go +++ b/pkg/pod/sharing.go @@ -50,7 +50,7 @@ func (p *Pod) PodShare(podName, sharedPodName string) (string, error) { return "", fmt.Errorf("pod does not exist") } - // Create pod account and get the address + // Create pod account and get the address accountInfo, err := p.acc.CreatePodAccount(index, false) if err != nil { // skipcq: TCV-001 return "", err @@ -72,7 +72,7 @@ func (p *Pod) PodShare(podName, sharedPodName string) (string, error) { if err != nil { // skipcq: TCV-001 return "", err } - ref, err := p.client.UploadBlob(data, 0, true, true) + ref, err := p.client.UploadBlob(data, 0, false) if err != nil { // skipcq: TCV-001 return "", err } @@ -81,6 +81,39 @@ func (p *Pod) PodShare(podName, sharedPodName string) (string, error) { return shareInfoRef.String(), nil } +// GetPodSharingInfo returns the raw shareInfo +func (p *Pod) GetPodSharingInfo(podName string) (*ShareInfo, error) { + // check if pods is present and get the index of the pod + podList, err := p.loadUserPods() + if err != nil { // skipcq: TCV-001 + return nil, err + } + if !p.checkIfPodPresent(podList, podName) { + return nil, ErrInvalidPodName + } + + index, podPassword := p.getIndexPassword(podList, podName) + if index == -1 { // skipcq: TCV-001 + return nil, fmt.Errorf("pod does not exist") + } + + // Create pod account and get the address + accountInfo, err := p.acc.CreatePodAccount(index, false) + if err != nil { // skipcq: TCV-001 + return nil, err + } + + address := accountInfo.GetAddress() + userAddress := p.acc.GetUserAccountInfo().GetAddress() + + return &ShareInfo{ + PodName: podName, + Password: podPassword, + Address: address.String(), + UserAddress: userAddress.String(), + }, nil +} + // ReceivePodInfo func (p *Pod) ReceivePodInfo(ref utils.Reference) (*ShareInfo, error) { data, resp, err := p.client.DownloadBlob(ref.Bytes()) @@ -99,7 +132,6 @@ func (p *Pod) ReceivePodInfo(ref utils.Reference) (*ShareInfo, error) { } return &shareInfo, nil - } // ReceivePod diff --git a/pkg/pod/stat.go b/pkg/pod/stat.go index 76db2b54..6723b028 100644 --- a/pkg/pod/stat.go +++ b/pkg/pod/stat.go @@ -16,6 +16,8 @@ limitations under the License. package pod +import "fmt" + // Stat represents a pod name and address type Stat struct { PodName string `json:"podName"` @@ -24,12 +26,31 @@ type Stat struct { // PodStat shows all the pod related information like podname and its current address. func (p *Pod) PodStat(podName string) (*Stat, error) { - podInfo, _, err := p.GetPodInfoFromPodMap(podName) + podInfo, _, err := p.GetPodInfo(podName) + if err == nil { + return &Stat{ + PodName: podInfo.GetPodName(), + PodAddress: podInfo.userAddress.String(), + }, nil + } + podList, err := p.loadUserPods() if err != nil { - return nil, ErrInvalidPodName + return nil, err + } + + index, _ := p.getIndexPassword(podList, podName) + if index == -1 { + return nil, fmt.Errorf("pod does not exist") + } + // Create pod account and other data structures + // create a child account for the userAddress and other data structures for the pod + accountInfo, err := p.acc.CreatePodAccount(index, false) + if err != nil { // skipcq: TCV-001 + return nil, err } + addr := accountInfo.GetAddress() return &Stat{ - PodName: podInfo.GetPodName(), - PodAddress: podInfo.userAddress.String(), + PodName: podName, + PodAddress: addr.String(), }, nil } diff --git a/pkg/pod/subscription.go b/pkg/pod/subscription.go new file mode 100644 index 00000000..101dfda8 --- /dev/null +++ b/pkg/pod/subscription.go @@ -0,0 +1,178 @@ +package pod + +import ( + "crypto/ecdsa" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "net/http" + + "github.com/ethereum/go-ethereum/common" + "github.com/fairdatasociety/fairOS-dfs/pkg/contracts/datahub" + "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" +) + +// ListPodInMarketplace will save the pod info in the subscriptionManager smart contract with its owner and price +// we keep the pod info in the smart contract, with a `list` flag +func (p *Pod) ListPodInMarketplace(podName, title, desc, thumbnail string, price uint64, daysValid uint16, category, nameHash [32]byte) error { + podList, err := p.loadUserPods() + if err != nil { // skipcq: TCV-001 + return err + } + if !p.checkIfPodPresent(podList, podName) { + return ErrInvalidPodName + } + + strAddr, _ := p.getAddressPassword(podList, podName) + if strAddr == "" { // skipcq: TCV-001 + return fmt.Errorf("pod does not exist") + } + + podAddress := common.HexToAddress(strAddr) + + return p.sm.AddPodToMarketplace(podAddress, common.HexToAddress(p.acc.GetUserAccountInfo().GetAddress().Hex()), podName, title, desc, thumbnail, price, daysValid, category, nameHash, p.acc.GetUserAccountInfo().GetPrivateKey()) +} + +// PodStatusInMarketplace will change the `list` flag for the pod so that it's not listed or gets re listed in the pod marketplace +func (p *Pod) PodStatusInMarketplace(subHash [32]byte, show bool) error { + hide := !show + return p.sm.HidePodFromMarketplace(common.HexToAddress(p.acc.GetUserAccountInfo().GetAddress().Hex()), subHash, hide, p.acc.GetUserAccountInfo().GetPrivateKey()) +} + +// ApproveSubscription will send a subscriptionManager request to the owner of the pod +func (p *Pod) ApproveSubscription(podName string, requestHash [32]byte, subscriberPublicKey *ecdsa.PublicKey) error { + a, _ := subscriberPublicKey.Curve.ScalarMult(subscriberPublicKey.X, subscriberPublicKey.Y, p.acc.GetUserAccountInfo().GetPrivateKey().D.Bytes()) + secret := sha256.Sum256(a.Bytes()) + + shareInfo, err := p.GetPodSharingInfo(podName) + if err != nil { + return err + } + + info := &rpc.ShareInfo{ + PodName: shareInfo.PodName, + Address: shareInfo.Address, + Password: shareInfo.Password, + UserAddress: shareInfo.UserAddress, + } + + return p.sm.AllowAccess(common.HexToAddress(p.acc.GetUserAccountInfo().GetAddress().Hex()), info, requestHash, secret, p.acc.GetUserAccountInfo().GetPrivateKey()) +} + +// EncryptUploadSubscriptionInfo will upload sub pod info into swarm +func (p *Pod) EncryptUploadSubscriptionInfo(podName string, subscriberPublicKey *ecdsa.PublicKey) (string, error) { + a, _ := subscriberPublicKey.Curve.ScalarMult(subscriberPublicKey.X, subscriberPublicKey.Y, p.acc.GetUserAccountInfo().GetPrivateKey().D.Bytes()) + secret := sha256.Sum256(a.Bytes()) + + shareInfo, err := p.GetPodSharingInfo(podName) + if err != nil { + return "", err + } + + info := &rpc.ShareInfo{ + PodName: shareInfo.PodName, + Address: shareInfo.Address, + Password: shareInfo.Password, + UserAddress: shareInfo.UserAddress, + } + + data, err := json.Marshal(info) + if err != nil { // skipcq: TCV-001 + return "", err + } + encData, err := utils.EncryptBytes(secret[:], data) + if err != nil { + return "", err + } + + ref, err := p.client.UploadBlob(encData, 0, false) + if err != nil { + return "", err + } + + return hex.EncodeToString(ref), nil +} + +// RequestSubscription will send a subscriptionManager request to the owner of the pod +// will create an escrow account and deposit the `price` +func (p *Pod) RequestSubscription(subHash, nameHash [32]byte) error { + return p.sm.RequestAccess(common.HexToAddress(p.acc.GetUserAccountInfo().GetAddress().Hex()), subHash, nameHash, p.acc.GetUserAccountInfo().GetPrivateKey()) +} + +// GetSubscriptions will query the smart contract and list my subscriptions +func (p *Pod) GetSubscriptions(nameHash [32]byte) ([]datahub.DataHubSubItem, error) { + return p.sm.GetSubscriptions(nameHash) +} + +// GetMarketplace will query the smart contract make the `list` all the pod from the marketplace +func (p *Pod) GetMarketplace() ([]datahub.DataHubSub, error) { + return p.sm.GetAllSubscribablePods() +} + +// GetSubscribablePodInfo will query the smart contract and get info by subHash +func (p *Pod) GetSubscribablePodInfo(subHash [32]byte) (*rpc.SubscriptionItemInfo, error) { + return p.sm.GetSubscribablePodInfo(subHash) +} + +// OpenSubscribedPod will open a subscribed pod +func (p *Pod) OpenSubscribedPod(reference []byte, ownerPublicKey *ecdsa.PublicKey) (*Info, error) { + a, _ := ownerPublicKey.Curve.ScalarMult(ownerPublicKey.X, ownerPublicKey.Y, p.acc.GetUserAccountInfo().GetPrivateKey().D.Bytes()) + secret := sha256.Sum256(a.Bytes()) + info, err := p.sm.GetSubscription(reference, secret) + if err != nil { + return nil, err + } + + shareInfo := &ShareInfo{ + PodName: info.PodName, + Address: info.Address, + Password: info.Password, + UserAddress: info.UserAddress, + } + return p.OpenFromShareInfo(shareInfo) +} + +// OpenSubscribedPodFromReference will open a subscribed pod +func (p *Pod) OpenSubscribedPodFromReference(reference string, ownerPublicKey *ecdsa.PublicKey) (*Info, error) { + a, _ := ownerPublicKey.Curve.ScalarMult(ownerPublicKey.X, ownerPublicKey.Y, p.acc.GetUserAccountInfo().GetPrivateKey().D.Bytes()) + secret := sha256.Sum256(a.Bytes()) + + ref, err := hex.DecodeString(reference) + if err != nil { // skipcq: TCV-001 + return nil, err + } + encData, resp, err := p.client.DownloadBlob(ref) + if err != nil { // skipcq: TCV-001 + return nil, err + } + + if resp != http.StatusOK { // skipcq: TCV-001 + return nil, fmt.Errorf("OpenSubscribedPodFromReference: could not get subscription info") + } + + data, err := utils.DecryptBytes(secret[:], encData) + if err != nil { + return nil, err + } + + var info *rpc.ShareInfo + err = json.Unmarshal(data, &info) + if err != nil { + return nil, err + } + + shareInfo := &ShareInfo{ + PodName: info.PodName, + Address: info.Address, + Password: info.Password, + UserAddress: info.UserAddress, + } + return p.OpenFromShareInfo(shareInfo) +} + +// GetSubRequests will get all owners sub requests +func (p *Pod) GetSubRequests() ([]datahub.DataHubSubRequest, error) { + return p.sm.GetSubRequests(common.HexToAddress(p.acc.GetUserAccountInfo().GetAddress().Hex())) +} diff --git a/pkg/pod/sync.go b/pkg/pod/sync.go index c31056d2..5faf45f4 100644 --- a/pkg/pod/sync.go +++ b/pkg/pod/sync.go @@ -29,11 +29,7 @@ func (p *Pod) SyncPod(podName string) error { return err } - if !p.IsPodOpened(podName) { - return ErrPodNotOpened - } - - podInfo, _, err := p.GetPodInfoFromPodMap(podName) + podInfo, _, err := p.GetPodInfo(podName) if err != nil { // skipcq: TCV-001 return err } @@ -54,11 +50,7 @@ func (p *Pod) SyncPodAsync(ctx context.Context, podName string) error { return err } - if !p.IsPodOpened(podName) { - return ErrPodNotOpened - } - - podInfo, _, err := p.GetPodInfoFromPodMap(podName) + podInfo, _, err := p.GetPodInfo(podName) if err != nil { // skipcq: TCV-001 return err } diff --git a/pkg/pod/utils.go b/pkg/pod/utils.go index 0e64d489..ac2d342f 100644 --- a/pkg/pod/utils.go +++ b/pkg/pod/utils.go @@ -24,11 +24,18 @@ import ( "github.com/fairdatasociety/fairOS-dfs/pkg/utils" ) -// IsPodOpened checks if a pod is open -func (p *Pod) IsPodOpened(podName string) bool { - p.podMu.Lock() - defer p.podMu.Unlock() - if _, ok := p.podMap[podName]; ok { +// IsOwnPodPresent checks if a pod is already present for user +func (p *Pod) IsOwnPodPresent(podName string) bool { + podName, err := CleanPodName(podName) + if err != nil { + return false + } + // check if pods is present and get free index + podList, err := p.loadUserPods() + if err != nil { // skipcq: TCV-001 + return false + } + if p.checkIfPodPresent(podList, podName) { return true } return false @@ -72,7 +79,7 @@ func (*Pod) GetName(inode *d.Inode) string { // GetAccountInfo returns the pod account info func (p *Pod) GetAccountInfo(podName string) (*account.Info, error) { - podInfo, _, err := p.GetPodInfoFromPodMap(podName) + podInfo, _, err := p.GetPodInfo(podName) if err != nil { return nil, err } diff --git a/pkg/subscriptionManager/rpc/manager.go b/pkg/subscriptionManager/rpc/manager.go new file mode 100644 index 00000000..812213f1 --- /dev/null +++ b/pkg/subscriptionManager/rpc/manager.go @@ -0,0 +1,363 @@ +package rpc + +import ( + "context" + "crypto/ecdsa" + "encoding/json" + "errors" + "fmt" + "math/big" + "net/http" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/fairdatasociety/fairOS-dfs/pkg/contracts" + "github.com/fairdatasociety/fairOS-dfs/pkg/contracts/datahub" + "github.com/fairdatasociety/fairOS-dfs/pkg/logging" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" +) + +const ( + additionalConfirmations = 1 + transactionReceiptTimeout = time.Minute * 2 + transactionReceiptPollingInterval = time.Second * 10 + + listMinFee = 1000000000000000 +) + +type SubscriptionInfoPutter interface { + UploadBlob(data []byte, tag uint32, encrypt bool) (address []byte, err error) + UploadBzz(data []byte, fileName string) (address []byte, err error) +} + +type SubscriptionInfoGetter interface { + DownloadBlob(address []byte) (data []byte, respCode int, err error) + DownloadBzz(address []byte) (data []byte, respCode int, err error) +} + +type SubscriptionItemInfo struct { + Category string `json:"category"` + Description string `json:"description"` + FdpSellerNameHash string `json:"sellerNameHash"` + ImageURL string `json:"imageUrl"` + PodAddress string `json:"podAddress"` + PodName string `json:"podName"` + Price string `json:"price"` + Title string `json:"title"` +} + +type Client struct { + c *ethclient.Client + putter SubscriptionInfoPutter + getter SubscriptionInfoGetter + datahub *datahub.Datahub + + logger logging.Logger +} + +// ShareInfo +type ShareInfo struct { + PodName string `json:"podName"` + Address string `json:"podAddress"` + Password string `json:"password"` + UserAddress string `json:"userAddress"` +} + +func (c *Client) AddPodToMarketplace(podAddress, owner common.Address, pod, title, desc, thumbnail string, price uint64, daysValid uint16, category, nameHash [32]byte, key *ecdsa.PrivateKey) error { + info := &SubscriptionItemInfo{ + Category: utils.Encode(category[:]), + Description: desc, + FdpSellerNameHash: utils.Encode(nameHash[:]), + ImageURL: thumbnail, + PodAddress: podAddress.Hex(), + PodName: pod, + Price: fmt.Sprintf("%d", price), + Title: title, + } + opts, err := c.newTransactor(key, owner, big.NewInt(listMinFee)) + if err != nil { + return err + } + + data, err := json.Marshal(info) + if err != nil { // skipcq: TCV-001 + return err + } + ref, err := c.putter.UploadBzz(data, fmt.Sprintf("%d.sub.json", time.Now().Unix())) + if err != nil { // skipcq: TCV-001 + return err + } + var a [32]byte + copy(a[:], ref) + + tx, err := c.datahub.ListSub(opts, nameHash, a, new(big.Int).SetUint64(price), category, podAddress, daysValid) + if err != nil { + return err + } + err = c.checkReceipt(tx) + if err != nil { + c.logger.Error("ListSub failed : ", err) + return err + } + c.logger.Info("ListSub with hash : ", tx.Hash().Hex()) + + return nil +} + +func (c *Client) HidePodFromMarketplace(owner common.Address, subHash [32]byte, hide bool, key *ecdsa.PrivateKey) error { + opts, err := c.newTransactor(key, owner, nil) + if err != nil { + return err + } + + tx, err := c.datahub.EnableSub(opts, subHash, !hide) + if err != nil { + return err + } + err = c.checkReceipt(tx) + if err != nil { + c.logger.Error("EnableSub failed : ", err) + return err + } + c.logger.Info("EnableSub with hash : ", tx.Hash().Hex()) + return nil +} + +func (c *Client) RequestAccess(subscriber common.Address, subHash, nameHash [32]byte, key *ecdsa.PrivateKey) error { + item, err := c.datahub.GetSubBy(&bind.CallOpts{}, subHash) + if err != nil { + return err + } + + opts, err := c.newTransactor(key, subscriber, item.Price) + if err != nil { + return err + } + + tx, err := c.datahub.BidSub(opts, subHash, nameHash) + if err != nil { + return err + } + err = c.checkReceipt(tx) + if err != nil { + c.logger.Error("BidSub failed : ", err) + return err + } + c.logger.Info("BidSub with hash : ", tx.Hash().Hex()) + return nil +} + +func (c *Client) AllowAccess(owner common.Address, shareInfo *ShareInfo, requestHash, secret [32]byte, key *ecdsa.PrivateKey) error { + opts, err := c.newTransactor(key, owner, nil) + if err != nil { + return err + } + + data, err := json.Marshal(shareInfo) + if err != nil { // skipcq: TCV-001 + return err + } + encData, err := utils.EncryptBytes(secret[:], data) + if err != nil { + return err + } + + ref, err := c.putter.UploadBlob(encData, 0, false) + if err != nil { + return err + } + + var fixedRef [32]byte + copy(fixedRef[:], ref) + + tx, err := c.datahub.SellSub(opts, requestHash, fixedRef) + if err != nil { + return err + } + err = c.checkReceipt(tx) + if err != nil { + c.logger.Error("SellSub failed : ", err) + return err + } + c.logger.Info("SellSub with hash : ", tx.Hash().Hex()) + return nil +} + +func (c *Client) GetSubscription(infoLocation []byte, secret [32]byte) (*ShareInfo, error) { + encData, respCode, err := c.getter.DownloadBlob(infoLocation[:]) + if err != nil { // skipcq: TCV-001 + return nil, err + } + if respCode != http.StatusOK { // skipcq: TCV-001 + return nil, fmt.Errorf("ReceivePodInfo: could not download blob") + } + + data, err := utils.DecryptBytes(secret[:], encData) + if err != nil { + return nil, err + } + var shareInfo *ShareInfo + err = json.Unmarshal(data, &shareInfo) + if err != nil { + return nil, err + } + + return shareInfo, nil +} + +func (c *Client) GetSubscribablePodInfo(subHash [32]byte) (*SubscriptionItemInfo, error) { + opts := &bind.CallOpts{} + item, err := c.datahub.GetSubBy(opts, subHash) + if err != nil { + return nil, err + } + data, respCode, err := c.getter.DownloadBzz(item.SwarmLocation[:]) + if err != nil { // skipcq: TCV-001 + return nil, err + } + if respCode != http.StatusOK { + return nil, fmt.Errorf("failed to get subscribable podInfo") + } + + info := &SubscriptionItemInfo{} + err = json.Unmarshal(data, info) + if err != nil { // skipcq: TCV-001 + return nil, err + } + return info, nil +} + +func (c *Client) GetSubscriptions(nameHash [32]byte) ([]datahub.DataHubSubItem, error) { + opts := &bind.CallOpts{} + return c.datahub.GetAllSubItemsForNameHash(opts, nameHash) +} + +func (c *Client) GetAllSubscribablePods() ([]datahub.DataHubSub, error) { + opts := &bind.CallOpts{} + return c.datahub.GetSubs(opts) +} + +func (c *Client) GetOwnSubscribablePods(owner common.Address) ([]datahub.DataHubSub, error) { + opts := &bind.CallOpts{} + s, err := c.datahub.GetSubs(opts) + if err != nil { + return nil, err + } + osp := []datahub.DataHubSub{} + for _, p := range s { + if p.Seller == owner { + osp = append(osp, p) + } + } + return osp, nil +} + +func (c *Client) GetSubRequests(owner common.Address) ([]datahub.DataHubSubRequest, error) { + opts := &bind.CallOpts{} + return c.datahub.GetSubRequests(opts, owner) +} + +func (c *Client) GetSub(subHash [32]byte) (*datahub.DataHubSub, error) { + opts := &bind.CallOpts{} + sub, err := c.datahub.GetSubBy(opts, subHash) + if err != nil { + return nil, err + } + return &sub, err +} + +func New(subConfig *contracts.SubscriptionConfig, logger logging.Logger, getter SubscriptionInfoGetter, putter SubscriptionInfoPutter) (*Client, error) { + c, err := ethclient.Dial(subConfig.RPC) + if err != nil { + return nil, fmt.Errorf("dial eth ensm: %w", err) + } + logger.Info("DataHubAddress : ", subConfig.DataHubAddress) + sMail, err := datahub.NewDatahub(common.HexToAddress(subConfig.DataHubAddress), c) + if err != nil { + return nil, err + } + + return &Client{ + c: c, + getter: getter, + putter: putter, + logger: logger, + datahub: sMail, + }, nil +} + +func (c *Client) newTransactor(key *ecdsa.PrivateKey, account common.Address, value *big.Int) (*bind.TransactOpts, error) { + nonce, err := c.c.PendingNonceAt(context.Background(), account) + if err != nil { + return nil, err + } + gasPrice, err := c.c.SuggestGasPrice(context.Background()) + if err != nil { + return nil, err + } + chainID, err := c.c.ChainID(context.Background()) + if err != nil { + return nil, err + } + opts, err := bind.NewKeyedTransactorWithChainID(key, chainID) + if err != nil { + return nil, err + } + opts.Nonce = big.NewInt(int64(nonce)) + opts.Value = value + opts.GasLimit = uint64(1000000) + opts.GasPrice = gasPrice + opts.From = account + return opts, nil +} + +func (c *Client) checkReceipt(tx *types.Transaction) error { + ctx, cancel := context.WithTimeout(context.Background(), transactionReceiptTimeout) + defer cancel() + + pollingInterval := transactionReceiptPollingInterval + for { + receipt, err := c.c.TransactionReceipt(ctx, tx.Hash()) + if err != nil { + if !errors.Is(err, ethereum.NotFound) { + return err + } + select { + case <-time.After(pollingInterval): + case <-ctx.Done(): + return ctx.Err() + } + continue + } + if receipt.Status == types.ReceiptStatusFailed { + return fmt.Errorf("transaction %s failed", tx.Hash().Hex()) + } + bn, err := c.c.BlockNumber(ctx) + if err != nil { + return err + } + + nextBlock := receipt.BlockNumber.Uint64() + 1 + + if bn >= nextBlock+additionalConfirmations { + _, err = c.c.HeaderByNumber(ctx, new(big.Int).SetUint64(nextBlock)) + if err != nil { + if !errors.Is(err, ethereum.NotFound) { + return err + } + } else { + return nil + } + } + + select { + case <-time.After(pollingInterval): + case <-ctx.Done(): + return errors.New("context timeout") + } + } +} diff --git a/pkg/subscriptionManager/rpc/mock/rpc.go b/pkg/subscriptionManager/rpc/mock/rpc.go new file mode 100644 index 00000000..c3cd15c8 --- /dev/null +++ b/pkg/subscriptionManager/rpc/mock/rpc.go @@ -0,0 +1,229 @@ +package mock + +import ( + "crypto/ecdsa" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "strings" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/fairdatasociety/fairOS-dfs/pkg/contracts/datahub" + "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" + goens "github.com/wealdtech/go-ens/v3" +) + +type SubscriptionManager struct { + lock sync.Mutex + listMap map[string]*datahub.DataHubSub + subscriptionMap map[string]*datahub.DataHubSubItem + requestMap map[string]*datahub.DataHubSubRequest + subPodInfo map[string]*rpc.SubscriptionItemInfo + subscribedMap map[string][]byte +} + +func (s *SubscriptionManager) GetSubscribablePodInfo(subHash [32]byte) (*rpc.SubscriptionItemInfo, error) { + s.lock.Lock() + defer s.lock.Unlock() + + return s.subPodInfo[utils.Encode(subHash[:])], nil +} + +// NewMockSubscriptionManager returns a new mock subscriptionManager manager client +func NewMockSubscriptionManager() *SubscriptionManager { + return &SubscriptionManager{ + listMap: make(map[string]*datahub.DataHubSub), + subscriptionMap: make(map[string]*datahub.DataHubSubItem), + requestMap: make(map[string]*datahub.DataHubSubRequest), + subPodInfo: make(map[string]*rpc.SubscriptionItemInfo), + subscribedMap: make(map[string][]byte), + } +} + +func (s *SubscriptionManager) AddPodToMarketplace(podAddress, owner common.Address, pod, title, desc, thumbnail string, price uint64, daysValid uint16, category, nameHash [32]byte, key *ecdsa.PrivateKey) error { + subHash, err := goens.NameHash(owner.Hex() + podAddress.String()) + if err != nil { + return err + } + i := &datahub.DataHubSub{ + SubHash: subHash, + FdpSellerNameHash: nameHash, + Seller: owner, + SwarmLocation: [32]byte{}, + Price: new(big.Int).SetUint64(price), + Active: true, + Earned: nil, + Bids: 0, + Sells: 0, + Reports: 0, + } + s.lock.Lock() + defer s.lock.Unlock() + + s.listMap[utils.Encode(subHash[:])] = i + s.subPodInfo[utils.Encode(subHash[:])] = &rpc.SubscriptionItemInfo{ + PodName: pod, + PodAddress: podAddress.Hex(), + } + + return nil +} + +func (s *SubscriptionManager) HidePodFromMarketplace(owner common.Address, subHash [32]byte, hide bool, key *ecdsa.PrivateKey) error { + s.lock.Lock() + defer s.lock.Unlock() + i, ok := s.listMap[utils.Encode(subHash[:])] + if !ok { + return fmt.Errorf("pod not listed") + } + if i.Seller != owner { + return fmt.Errorf("not the owner") + } + i.Active = !hide + return nil +} + +func (s *SubscriptionManager) RequestAccess(subscriber common.Address, subHash, nameHash [32]byte, key *ecdsa.PrivateKey) error { + s.lock.Lock() + defer s.lock.Unlock() + i, ok := s.listMap[utils.Encode(subHash[:])] + if !ok { + return fmt.Errorf("pod not listed") + } + if !i.Active { + return fmt.Errorf("pod not listed") + } + reqHash, err := goens.NameHash(subscriber.Hex() + utils.Encode(nameHash[:])) + if err != nil { + return err + } + s.requestMap[utils.Encode(reqHash[:])] = &datahub.DataHubSubRequest{ + FdpBuyerNameHash: nameHash, + Buyer: subscriber, + SubHash: subHash, + RequestHash: reqHash, + } + return nil +} + +func (s *SubscriptionManager) GetSubRequests(owner common.Address) ([]datahub.DataHubSubRequest, error) { + s.lock.Lock() + defer s.lock.Unlock() + + requests := []datahub.DataHubSubRequest{} + for _, r := range s.requestMap { + sub := s.listMap[utils.Encode(r.SubHash[:])] + if sub.Seller == owner { + requests = append(requests, *r) + } + } + + return requests, nil +} + +func (s *SubscriptionManager) AllowAccess(owner common.Address, si *rpc.ShareInfo, requestHash, secret [32]byte, key *ecdsa.PrivateKey) error { + s.lock.Lock() + defer s.lock.Unlock() + + i, ok := s.requestMap[utils.Encode(requestHash[:])] + if !ok { + return fmt.Errorf("request not available") + } + + addrBytes, _ := utils.GetRandBytes(32) + + var addr [32]byte + copy(addr[:], addrBytes) + item := &datahub.DataHubSubItem{ + SubHash: i.SubHash, + UnlockKeyLocation: addr, + ValidTill: new(big.Int).SetInt64(time.Now().AddDate(0, 1, 0).Unix()), + } + s.subscriptionMap[utils.Encode(i.FdpBuyerNameHash[:])+utils.Encode(requestHash[:])] = item + + dt, err := json.Marshal(si) + if err != nil { + return err + } + + encDt, err := utils.EncryptBytes(secret[:], dt) + if err != nil { + return err + } + + s.subscribedMap[hex.EncodeToString(addrBytes)] = encDt + + return nil +} + +func (s *SubscriptionManager) GetSubscriptions(nameHash [32]byte) ([]datahub.DataHubSubItem, error) { + s.lock.Lock() + defer s.lock.Unlock() + + subscriber := utils.Encode(nameHash[:]) + pods := []datahub.DataHubSubItem{} + for i, v := range s.subscriptionMap { + if strings.HasPrefix(i, subscriber) { + pods = append(pods, *v) + } + } + + return pods, nil +} + +func (s *SubscriptionManager) GetSubscription(infoLocation []byte, secret [32]byte) (*rpc.ShareInfo, error) { + s.lock.Lock() + defer s.lock.Unlock() + + encDt := s.subscribedMap[hex.EncodeToString(infoLocation)] + dt, err := utils.DecryptBytes(secret[:], encDt) + if err != nil { + return nil, err + } + + ip := &rpc.ShareInfo{} + err = json.Unmarshal(dt, ip) + if err != nil { + return nil, err + } + return ip, nil +} + +func (s *SubscriptionManager) GetAllSubscribablePods() ([]datahub.DataHubSub, error) { + s.lock.Lock() + defer s.lock.Unlock() + pods := []datahub.DataHubSub{} + for _, v := range s.listMap { + if v.Active { + pods = append(pods, *v) + } + } + return pods, nil +} + +func (s *SubscriptionManager) GetOwnSubscribablePods(owner common.Address) ([]datahub.DataHubSub, error) { + s.lock.Lock() + defer s.lock.Unlock() + + pods := []datahub.DataHubSub{} + for _, v := range s.listMap { + if v.Seller == owner { + pods = append(pods, *v) + } + } + return pods, nil +} + +func (s *SubscriptionManager) GetSub(subHash [32]byte) (*datahub.DataHubSub, error) { + s.lock.Lock() + defer s.lock.Unlock() + i, ok := s.listMap[utils.Encode(subHash[:])] + if ok { + return i, nil + } + return nil, fmt.Errorf("pod not found") +} diff --git a/pkg/subscriptionManager/subscriptionManager.go b/pkg/subscriptionManager/subscriptionManager.go new file mode 100644 index 00000000..a25c8782 --- /dev/null +++ b/pkg/subscriptionManager/subscriptionManager.go @@ -0,0 +1,23 @@ +package subscriptionManager + +import ( + "crypto/ecdsa" + + "github.com/ethereum/go-ethereum/common" + "github.com/fairdatasociety/fairOS-dfs/pkg/contracts/datahub" + "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc" +) + +type SubscriptionManager interface { + AddPodToMarketplace(podAddress, owner common.Address, pod, title, desc, thumbnail string, price uint64, daysValid uint16, category, nameHash [32]byte, key *ecdsa.PrivateKey) error + HidePodFromMarketplace(owner common.Address, subHash [32]byte, hide bool, key *ecdsa.PrivateKey) error + RequestAccess(subscriber common.Address, subHash, nameHash [32]byte, key *ecdsa.PrivateKey) error + AllowAccess(owner common.Address, si *rpc.ShareInfo, requestHash, secret [32]byte, key *ecdsa.PrivateKey) error + GetSubscription(infoLocation []byte, secret [32]byte) (*rpc.ShareInfo, error) + GetSubscriptions(nameHash [32]byte) ([]datahub.DataHubSubItem, error) + GetAllSubscribablePods() ([]datahub.DataHubSub, error) + GetOwnSubscribablePods(owner common.Address) ([]datahub.DataHubSub, error) + GetSubscribablePodInfo(subHash [32]byte) (*rpc.SubscriptionItemInfo, error) + GetSubRequests(owner common.Address) ([]datahub.DataHubSubRequest, error) + GetSub(subHash [32]byte) (*datahub.DataHubSub, error) +} diff --git a/pkg/test/close_test.go b/pkg/test/close_test.go index a0ea097e..8c64fb4f 100644 --- a/pkg/test/close_test.go +++ b/pkg/test/close_test.go @@ -22,6 +22,8 @@ import ( "testing" "time" + mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/plexsysio/taskmanager" @@ -48,7 +50,9 @@ func TestClose(t *testing.T) { _ = tm.Stop(context.Background()) }() - pod1 := pod.NewPod(mockClient, fd, acc, tm, logger) + sm := mock2.NewMockSubscriptionManager() + + pod1 := pod.NewPod(mockClient, fd, acc, tm, sm, logger) podName1 := "test1" t.Run("close-pod", func(t *testing.T) { @@ -59,12 +63,6 @@ func TestClose(t *testing.T) { t.Fatalf("error creating pod %s", podName1) } - // make root dir so that other directories can be added - err = info.GetDirectory().MkRootDir("pod1", podPassword, info.GetPodAddress(), info.GetFeed()) - if err != nil { - t.Fatal(err) - } - // create some dir and files addFilesAndDirectories(t, info, pod1, podName1, podPassword) @@ -76,23 +74,31 @@ func TestClose(t *testing.T) { if gotPodInfo != nil { t.Fatalf("pod not closed") } - dirObject := info.GetDirectory() - dirInode1 := dirObject.GetDirFromDirectoryMap("/parentDir/subDir1") - if dirInode1 != nil { - t.Fatalf("dir not closed properly") + + gotPodInfo, _, err = pod1.GetPodInfo(podName1) + if err != nil { + t.Fatalf("pod should be open") + } + if gotPodInfo == nil { + t.Fatalf("pod should be open") + } + dirObject := gotPodInfo.GetDirectory() + dirInode1 := dirObject.GetInode(podPassword, "/parentDir/subDir1") + if dirInode1 == nil { + t.Fatalf("dir should nil be nil") } - dirInode2 := dirObject.GetDirFromDirectoryMap("/parentDir/subDir2") - if dirInode2 != nil { - t.Fatalf("dir not closed properly") + dirInode2 := dirObject.GetInode(podPassword, "/parentDir/subDir2") + if dirInode2 == nil { + t.Fatalf("dir should nil be nil") } - fileObject := info.GetFile() - fileMeta1 := fileObject.GetFromFileMap("/parentDir/file1") - if fileMeta1 != nil { - t.Fatalf("file not closed properly") + fileObject := gotPodInfo.GetFile() + fileMeta1 := fileObject.GetInode(podPassword, "/parentDir/file1") + if fileMeta1 == nil { + t.Fatalf("file should nil be nil") } - fileMeta2 := fileObject.GetFromFileMap("/parentDir/file2") - if fileMeta2 != nil { - t.Fatalf("file not closed properly") + fileMeta2 := fileObject.GetInode(podPassword, "/parentDir/file2") + if fileMeta2 == nil { + t.Fatalf("file should nil be nil") } }) diff --git a/pkg/test/del_test.go b/pkg/test/del_test.go index 1f9672da..731dbfef 100644 --- a/pkg/test/del_test.go +++ b/pkg/test/del_test.go @@ -24,6 +24,8 @@ import ( "testing" "time" + mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/plexsysio/taskmanager" @@ -50,8 +52,9 @@ func TestPodDelete(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock2.NewMockSubscriptionManager() - pod1 := pod.NewPod(mockClient, fd, acc, tm, logger) + pod1 := pod.NewPod(mockClient, fd, acc, tm, sm, logger) podName1 := "test1" podName2 := "test2" @@ -91,7 +94,7 @@ func TestPodDelete(t *testing.T) { t.Fatalf("delete failed") } - infoGot, _, err := pod1.GetPodInfoFromPodMap(podName1) + infoGot, _, err := pod1.GetPodInfo(podName1) if err == nil { t.Fatalf("pod not deleted from map") } @@ -143,7 +146,7 @@ func TestPodDelete(t *testing.T) { t.Fatalf("delete pod failed") } - infoGot, _, err := pod1.GetPodInfoFromPodMap(podName1) + infoGot, _, err := pod1.GetPodInfo(podName1) if err == nil { t.Fatalf("pod not deleted from map") } @@ -151,7 +154,7 @@ func TestPodDelete(t *testing.T) { t.Fatalf("pod not deleted from map") } - _, _, err = pod1.GetPodInfoFromPodMap(podName2) + _, _, err = pod1.GetPodInfo(podName2) if err != nil { t.Fatalf("removed wrong pod") } diff --git a/pkg/test/delete_test.go b/pkg/test/delete_test.go index f400865a..9d58e483 100644 --- a/pkg/test/delete_test.go +++ b/pkg/test/delete_test.go @@ -23,12 +23,13 @@ import ( "testing" "time" - "github.com/plexsysio/taskmanager" + mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/ensm/eth/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" "github.com/fairdatasociety/fairOS-dfs/pkg/user" + "github.com/plexsysio/taskmanager" ) func TestDelete(t *testing.T) { @@ -38,12 +39,13 @@ func TestDelete(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock3.NewMockSubscriptionManager() t.Run("delete-user", func(t *testing.T) { ens := mock2.NewMockNamespaceManager() // create user userObject := user.NewUsers(mockClient, ens, logger) - _, _, _, _, ui, err := userObject.CreateNewUserV2("user1", "password1twelve", "", "", tm) + _, _, _, _, ui, err := userObject.CreateNewUserV2("user1", "password1twelve", "", "", tm, sm) if err != nil { t.Fatal(err) } diff --git a/pkg/test/fork_test.go b/pkg/test/fork_test.go index 99d206fd..1b22ab45 100644 --- a/pkg/test/fork_test.go +++ b/pkg/test/fork_test.go @@ -22,6 +22,8 @@ import ( "testing" "time" + mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/account" "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" @@ -44,7 +46,9 @@ func TestFork(t *testing.T) { _ = tm.Stop(context.Background()) }() fd := feed.New(acc.GetUserAccountInfo(), mockClient, logger) - pod1 := pod.NewPod(mockClient, fd, acc, tm, logger) + sm := mock2.NewMockSubscriptionManager() + + pod1 := pod.NewPod(mockClient, fd, acc, tm, sm, logger) podName1 := "test1" t.Run("fork-pod", func(t *testing.T) { @@ -76,22 +80,9 @@ func TestFork(t *testing.T) { t.Fatal(err) } - // open fork pod - pi, err := pod1.OpenPod(forkName) - if err != nil { - t.Fatal(err) - } - - // create the root directory - err = pi.GetDirectory().MkRootDir(pi.GetPodName(), podPassword, pi.GetPodAddress(), pi.GetFeed()) - if err != nil { - t.Fatal(err) - } - err = pod1.PodFork(podName1, forkName) if err != nil { t.Fatal(err) - } // open the pod ths triggers sync too gotInfo, err := pod1.OpenPod(forkName) @@ -101,7 +92,7 @@ func TestFork(t *testing.T) { // validate if the directory and files are synced dirObject := gotInfo.GetDirectory() - dirInode1 := dirObject.GetDirFromDirectoryMap("/parentDir/subDir1") + dirInode1 := dirObject.GetInode(podPassword, "/parentDir/subDir1") if dirInode1 == nil { t.Fatalf("invalid dir entry") } @@ -111,7 +102,7 @@ func TestFork(t *testing.T) { if dirInode1.Meta.Name != "subDir1" { t.Fatalf("invalid dir entry") } - dirInode2 := dirObject.GetDirFromDirectoryMap("/parentDir/subDir2") + dirInode2 := dirObject.GetInode(podPassword, "/parentDir/subDir2") if dirInode2 == nil { t.Fatalf("invalid dir entry") } @@ -123,7 +114,7 @@ func TestFork(t *testing.T) { } fileObject := gotInfo.GetFile() - fileMeta1 := fileObject.GetFromFileMap("/parentDir/file1") + fileMeta1 := fileObject.GetInode(podPassword, "/parentDir/file1") if fileMeta1 == nil { t.Fatalf("invalid file meta") } @@ -139,7 +130,7 @@ func TestFork(t *testing.T) { if fileMeta1.BlockSize != uint32(10) { t.Fatalf("invalid block size") } - fileMeta2 := fileObject.GetFromFileMap("/parentDir/file2") + fileMeta2 := fileObject.GetInode(podPassword, "/parentDir/file2") if fileMeta2 == nil { t.Fatalf("invalid file meta") } diff --git a/pkg/test/integration_test.go b/pkg/test/integration_test.go index af6cc997..c9e03be8 100644 --- a/pkg/test/integration_test.go +++ b/pkg/test/integration_test.go @@ -124,14 +124,13 @@ func TestLiteUser(t *testing.T) { for _, v := range entries { if v.isDir { - - err = dfsApi.Mkdir(podRequest.PodName, v.path, sessionId) + err = dfsApi.Mkdir(podRequest.PodName, v.path, sessionId, 0) if err != nil { t.Fatal(err) } } else { reader := &io.LimitedReader{R: rand.Reader, N: v.size} - err = dfsApi.UploadFile(podRequest.PodName, filepath.Base(v.path), sessionId, v.size, reader, filepath.Dir(v.path), "", 100000, false) + err = dfsApi.UploadFile(podRequest.PodName, filepath.Base(v.path), sessionId, v.size, reader, filepath.Dir(v.path), "", 100000, 0, false) if err != nil { t.Fatal(err) } @@ -142,14 +141,12 @@ func TestLiteUser(t *testing.T) { if v.isDir { _, err := dfsApi.DirectoryStat(podRequest.PodName, v.path, sessionId) if err != nil { - t.Fatal(err) - + t.Fatal("DirectoryStat failed for ", v.path, err) } } else { _, err := dfsApi.FileStat(podRequest.PodName, v.path, sessionId) if err != nil { t.Fatal(err) - } } } @@ -301,13 +298,11 @@ func TestLiteUser(t *testing.T) { _, err := dfsApi.DirectoryStat(podRequest.PodName, v.path, sessionId) if err != nil { t.Fatal(err) - } } else { _, err := dfsApi.FileStat(podRequest.PodName, v.path, sessionId) if err != nil { - t.Fatal(err) - + t.Fatal(err, v.path) } } } diff --git a/pkg/test/lite_test.go b/pkg/test/lite_test.go index 5060b1ca..b9180f58 100644 --- a/pkg/test/lite_test.go +++ b/pkg/test/lite_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/ensm/eth/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -21,13 +23,14 @@ func TestLite(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock3.NewMockSubscriptionManager() t.Run("new-blank-username", func(t *testing.T) { ens := mock2.NewMockNamespaceManager() // create user userObject := user.NewUsers(mockClient, ens, logger) - _, _, _, err := userObject.LoadLiteUser("", "password1", "", "", tm) + _, _, _, err := userObject.LoadLiteUser("", "password1", "", "", tm, sm) if !errors.Is(err, user.ErrInvalidUserName) { t.Fatal(err) } @@ -38,7 +41,7 @@ func TestLite(t *testing.T) { // create user userObject := user.NewUsers(mockClient, ens, logger) - mnemonic, _, ui, err := userObject.LoadLiteUser("user1", "password1", "", "", tm) + mnemonic, _, ui, err := userObject.LoadLiteUser("user1", "password1", "", "", tm, sm) if err != nil { t.Fatal(err) } diff --git a/pkg/test/login_test.go b/pkg/test/login_test.go index c83615ef..0102fae1 100644 --- a/pkg/test/login_test.go +++ b/pkg/test/login_test.go @@ -24,6 +24,8 @@ import ( "testing" "time" + mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/ensm/eth/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -40,12 +42,13 @@ func TestLogin(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock3.NewMockSubscriptionManager() t.Run("login-user", func(t *testing.T) { ens := mock2.NewMockNamespaceManager() // create user userObject := user.NewUsers(mockClient, ens, logger) - _, _, _, _, ui, err := userObject.CreateNewUserV2("7e4567e7cb003804992eef11fd5c757275a4c", "password1twelve", "", "", tm) + _, _, _, _, ui, err := userObject.CreateNewUserV2("7e4567e7cb003804992eef11fd5c757275a4c", "password1twelve", "", "", tm, sm) if err != nil { t.Fatal(err) } @@ -56,18 +59,18 @@ func TestLogin(t *testing.T) { t.Fatal(err) } - _, _, _, err = userObject.LoginUserV2("not_an_username", "password1", mockClient, tm, "") + _, _, _, err = userObject.LoginUserV2("not_an_username", "password1", mockClient, tm, sm, "") if !errors.Is(err, user.ErrUserNameNotFound) { t.Fatal(err) } - _, _, _, err = userObject.LoginUserV2("7e4567e7cb003804992eef11fd5c757275a4c", "wrong_password", mockClient, tm, "") + _, _, _, err = userObject.LoginUserV2("7e4567e7cb003804992eef11fd5c757275a4c", "wrong_password", mockClient, tm, sm, "") if !errors.Is(err, user.ErrInvalidPassword) { t.Fatal(err) } // addUserAndSessionToMap user again - ui1, _, _, err := userObject.LoginUserV2("7e4567e7cb003804992eef11fd5c757275a4c", "password1twelve", mockClient, tm, "") + ui1, _, _, err := userObject.LoginUserV2("7e4567e7cb003804992eef11fd5c757275a4c", "password1twelve", mockClient, tm, sm, "") if err != nil { t.Fatal(err) } @@ -98,12 +101,12 @@ func TestLogin(t *testing.T) { pass := "password1password1" //create user userObject := user.NewUsers(mockClient, ens, logger) - _, mnemonic, _, _, ui, err := userObject.CreateNewUserV2(user1, pass, "", "", tm) + _, mnemonic, _, _, ui, err := userObject.CreateNewUserV2(user1, pass, "", "", tm, sm) if err != nil { t.Fatal(err) } - _, _, _, _, _, err = userObject.CreateNewUserV2(user1, pass, "", "", tm) + _, _, _, _, _, err = userObject.CreateNewUserV2(user1, pass, "", "", tm, sm) if !errors.Is(err, user.ErrUserAlreadyPresent) { t.Fatal(err) } @@ -129,17 +132,17 @@ func TestLogin(t *testing.T) { t.Fatalf("invalid mnemonic") } - _, _, _, _, _, err = userObject.CreateNewUserV2(user1, pass+pass, mnemonic, "", tm) + _, _, _, _, _, err = userObject.CreateNewUserV2(user1, pass+pass, mnemonic, "", tm, sm) if err != nil { t.Fatal(err) } - login1, _, _, err := userObject.LoginUserV2(user1, pass, mockClient, tm, "") + login1, _, _, err := userObject.LoginUserV2(user1, pass, mockClient, tm, sm, "") if err != nil { t.Fatal(err) } - login2, _, _, err := userObject.LoginUserV2(user1, pass+pass, mockClient, tm, "") + login2, _, _, err := userObject.LoginUserV2(user1, pass+pass, mockClient, tm, sm, "") if err != nil { t.Fatal(err) } @@ -156,12 +159,12 @@ func TestLogin(t *testing.T) { //create user userObject := user.NewUsers(mockClient, ens, logger) pass := "password1password1" - _, mnemonic, _, _, ui, err := userObject.CreateNewUserV2(user1, pass, "", "", tm) + _, mnemonic, _, _, ui, err := userObject.CreateNewUserV2(user1, pass, "", "", tm, sm) if err != nil { t.Fatal(err) } - _, _, _, _, _, err = userObject.CreateNewUserV2(user1, pass, "", "", tm) + _, _, _, _, _, err = userObject.CreateNewUserV2(user1, pass, "", "", tm, sm) if !errors.Is(err, user.ErrUserAlreadyPresent) { t.Fatal(err) } @@ -199,17 +202,17 @@ func TestLogin(t *testing.T) { t.Fatalf("error creating pod %s : %s", podName1, err.Error()) } - _, _, _, _, ui2, err := userObject.CreateNewUserV2(user1, pass+pass, mnemonic, "", tm) + _, _, _, _, ui2, err := userObject.CreateNewUserV2(user1, pass+pass, mnemonic, "", tm, sm) if err != nil { t.Fatal(err) } - login1, _, _, err := userObject.LoginUserV2(user1, pass, mockClient, tm, "") + login1, _, _, err := userObject.LoginUserV2(user1, pass, mockClient, tm, sm, "") if err != nil { t.Fatal(err) } - login2, _, _, err := userObject.LoginUserV2(user1, pass+pass, mockClient, tm, "") + login2, _, _, err := userObject.LoginUserV2(user1, pass+pass, mockClient, tm, sm, "") if err != nil { t.Fatal(err) } diff --git a/pkg/test/logout_test.go b/pkg/test/logout_test.go index 6f1d50cc..fba41de7 100644 --- a/pkg/test/logout_test.go +++ b/pkg/test/logout_test.go @@ -23,6 +23,8 @@ import ( "testing" "time" + mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/plexsysio/taskmanager" "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" @@ -38,13 +40,14 @@ func TestLogout(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock3.NewMockSubscriptionManager() t.Run("logout-user", func(t *testing.T) { ens := mock2.NewMockNamespaceManager() // create user userObject := user.NewUsers(mockClient, ens, logger) - _, _, _, _, ui, err := userObject.CreateNewUserV2("user1", "password1twelve", "", "", tm) + _, _, _, _, ui, err := userObject.CreateNewUserV2("user1", "password1twelve", "", "", tm, sm) if err != nil { t.Fatal(err) } diff --git a/pkg/test/ls_test.go b/pkg/test/ls_test.go index f6e005d6..b64b9b73 100644 --- a/pkg/test/ls_test.go +++ b/pkg/test/ls_test.go @@ -22,6 +22,8 @@ import ( "testing" "time" + mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" @@ -44,8 +46,9 @@ func TestPod_ListPods(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock2.NewMockSubscriptionManager() - pod1 := pod.NewPod(mockClient, fd, acc, tm, logger) + pod1 := pod.NewPod(mockClient, fd, acc, tm, sm, logger) _, _, err := acc.CreateUserAccount("") if err != nil { t.Fatal(err) diff --git a/pkg/test/max_pod_test.go b/pkg/test/max_pod_test.go index df27c1ac..4d568e55 100644 --- a/pkg/test/max_pod_test.go +++ b/pkg/test/max_pod_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/plexsysio/taskmanager" "github.com/fairdatasociety/fairOS-dfs/pkg/account" @@ -30,8 +32,9 @@ func TestMaxPods(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock3.NewMockSubscriptionManager() - pod1 := pod.NewPod(mockClient, fd, acc, tm, logger) + pod1 := pod.NewPod(mockClient, fd, acc, tm, sm, logger) t.Run("create-max-pods", func(t *testing.T) { // t.SkipNow() diff --git a/pkg/test/new_test.go b/pkg/test/new_test.go index 8ff081e7..ee64b6ce 100644 --- a/pkg/test/new_test.go +++ b/pkg/test/new_test.go @@ -23,6 +23,8 @@ import ( "testing" "time" + mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/plexsysio/taskmanager" "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" @@ -38,13 +40,14 @@ func TestNew(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock3.NewMockSubscriptionManager() t.Run("new-blank-username", func(t *testing.T) { ens := mock2.NewMockNamespaceManager() // create user userObject := user.NewUsers(mockClient, ens, logger) - _, _, _, _, _, err := userObject.CreateNewUserV2("", "password1", "", "", tm) + _, _, _, _, _, err := userObject.CreateNewUserV2("", "password1", "", "", tm, sm) if !errors.Is(err, user.ErrBlankUsername) { t.Fatal(err) } @@ -55,17 +58,17 @@ func TestNew(t *testing.T) { // create user userObject := user.NewUsers(mockClient, ens, logger) - _, _, _, _, _, err := userObject.CreateNewUserV2("user1", "password1", "", "", tm) + _, _, _, _, _, err := userObject.CreateNewUserV2("user1", "password1", "", "", tm, sm) if err != nil && !errors.Is(err, user.ErrPasswordTooSmall) { t.Fatal(err) } - _, mnemonic, _, _, ui, err := userObject.CreateNewUserV2("user1", "password1twelve", "", "", tm) + _, mnemonic, _, _, ui, err := userObject.CreateNewUserV2("user1", "password1twelve", "", "", tm, sm) if err != nil { t.Fatal(err) } - _, _, _, _, _, err = userObject.CreateNewUserV2("user1", "password1twelve", "", "", tm) + _, _, _, _, _, err = userObject.CreateNewUserV2("user1", "password1twelve", "", "", tm, sm) if !errors.Is(err, user.ErrUserAlreadyPresent) { t.Fatal(err) } @@ -98,12 +101,12 @@ func TestNew(t *testing.T) { //create user userObject := user.NewUsers(mockClient, ens, logger) pass := "password1password1" - _, mnemonic, _, _, ui, err := userObject.CreateNewUserV2(user1, pass, "", "", tm) + _, mnemonic, _, _, ui, err := userObject.CreateNewUserV2(user1, pass, "", "", tm, sm) if err != nil { t.Fatal(err) } - _, _, _, _, _, err = userObject.CreateNewUserV2(user1, pass, "", "", tm) + _, _, _, _, _, err = userObject.CreateNewUserV2(user1, pass, "", "", tm, sm) if !errors.Is(err, user.ErrUserAlreadyPresent) { t.Fatal(err) } @@ -129,7 +132,7 @@ func TestNew(t *testing.T) { t.Fatalf("invalid mnemonic") } - _, _, _, _, _, err = userObject.CreateNewUserV2(user1, pass+pass, mnemonic, "", tm) + _, _, _, _, _, err = userObject.CreateNewUserV2(user1, pass+pass, mnemonic, "", tm, sm) if err != nil { t.Fatal(err) } diff --git a/pkg/test/open_test.go b/pkg/test/open_test.go index a7774939..e39bdb47 100644 --- a/pkg/test/open_test.go +++ b/pkg/test/open_test.go @@ -25,6 +25,8 @@ import ( "testing" "time" + mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/plexsysio/taskmanager" @@ -49,9 +51,10 @@ func TestOpen(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock2.NewMockSubscriptionManager() fd := feed.New(acc.GetUserAccountInfo(), mockClient, logger) - pod1 := pod.NewPod(mockClient, fd, acc, tm, logger) + pod1 := pod.NewPod(mockClient, fd, acc, tm, sm, logger) podName1 := "test1" podName2 := "test2" @@ -88,7 +91,7 @@ func TestOpen(t *testing.T) { if podInfo == nil { t.Fatalf("pod not opened") } - gotPodInfo, _, err := pod1.GetPodInfoFromPodMap(podName1) + gotPodInfo, _, err := pod1.GetPodInfo(podName1) if err != nil { t.Fatalf("pod not opened") } @@ -133,7 +136,7 @@ func TestOpen(t *testing.T) { if podInfo == nil { t.Fatalf("pod not opened") } - gotPodInfo, _, err := pod1.GetPodInfoFromPodMap(podName2) + gotPodInfo, _, err := pod1.GetPodInfo(podName2) if err != nil { t.Fatalf("pod not opened") } @@ -178,13 +181,13 @@ func uploadFile(t *testing.T, fileObject *file.File, filePath, fileName, compres } // upload the temp file - return content, fileObject.Upload(f1, fileName, fileSize, blockSize, filePath, compression, podPassword) + return content, fileObject.Upload(f1, fileName, fileSize, blockSize, 0, filePath, compression, podPassword) } func addFilesAndDirectories(t *testing.T, info *pod.Info, pod1 *pod.Pod, podName1, podPassword string) { t.Helper() dirObject := info.GetDirectory() - err := dirObject.MkDir("/parentDir", podPassword) + err := dirObject.MkDir("/parentDir", podPassword, 0) if err != nil { t.Fatal(err) } @@ -198,11 +201,11 @@ func addFilesAndDirectories(t *testing.T, info *pod.Info, pod1 *pod.Pod, podName } // populate the directory with few directory and files - err = dirObject.MkDir("/parentDir/subDir1", podPassword) + err = dirObject.MkDir("/parentDir/subDir1", podPassword, 0) if err != nil { t.Fatal(err) } - err = dirObject.MkDir("/parentDir/subDir2", podPassword) + err = dirObject.MkDir("/parentDir/subDir2", podPassword, 0) if err != nil { t.Fatal(err) } @@ -232,7 +235,7 @@ func addFilesAndDirectories(t *testing.T, info *pod.Info, pod1 *pod.Pod, podName // close the pod err = pod1.ClosePod(podName1) - if !errors.Is(err, pod.ErrPodNotOpened) { + if err == nil { t.Fatal("pod should not be open") } } diff --git a/pkg/test/pod_new_test.go b/pkg/test/pod_new_test.go index 89abd093..8fd7d3f4 100644 --- a/pkg/test/pod_new_test.go +++ b/pkg/test/pod_new_test.go @@ -24,6 +24,8 @@ import ( "testing" "time" + mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/plexsysio/taskmanager" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" @@ -48,7 +50,9 @@ func TestPodNew(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() - pod1 := pod.NewPod(mockClient, fd, acc, tm, logger) + sm := mock2.NewMockSubscriptionManager() + + pod1 := pod.NewPod(mockClient, fd, acc, tm, sm, logger) podName1 := "test1" podName2 := "test2" @@ -98,7 +102,7 @@ func TestPodNew(t *testing.T) { t.Fatalf("podName is not %s", podName1) } - infoGot, _, err := pod1.GetPodInfoFromPodMap(podName1) + infoGot, _, err := pod1.GetPodInfo(podName1) if err != nil { t.Fatalf("could not get pod from podMap") } @@ -132,7 +136,7 @@ func TestPodNew(t *testing.T) { t.Fatalf("podName is not %s", podName2) } - infoGot, _, err := pod1.GetPodInfoFromPodMap(podName2) + infoGot, _, err := pod1.GetPodInfo(podName2) if err != nil { t.Fatalf("could not get pod from podMap") } diff --git a/pkg/test/pod_sharing_test.go b/pkg/test/pod_sharing_test.go index ce0b00ed..0995e91c 100644 --- a/pkg/test/pod_sharing_test.go +++ b/pkg/test/pod_sharing_test.go @@ -23,6 +23,8 @@ import ( "testing" "time" + mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/plexsysio/taskmanager" "github.com/fairdatasociety/fairOS-dfs/pkg/account" @@ -46,7 +48,9 @@ func TestShare(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() - pod1 := pod.NewPod(mockClient, fd, acc, tm, logger) + sm := mock2.NewMockSubscriptionManager() + + pod1 := pod.NewPod(mockClient, fd, acc, tm, sm, logger) podName1 := "test1" acc2 := account.New(logger) @@ -55,7 +59,7 @@ func TestShare(t *testing.T) { t.Fatal(err) } fd2 := feed.New(acc2.GetUserAccountInfo(), mockClient, logger) - pod2 := pod.NewPod(mockClient, fd2, acc2, tm, logger) + pod2 := pod.NewPod(mockClient, fd2, acc2, tm, sm, logger) podName2 := "test2" acc3 := account.New(logger) @@ -64,7 +68,7 @@ func TestShare(t *testing.T) { t.Fatal(err) } fd3 := feed.New(acc3.GetUserAccountInfo(), mockClient, logger) - pod3 := pod.NewPod(mockClient, fd3, acc3, tm, logger) + pod3 := pod.NewPod(mockClient, fd3, acc3, tm, sm, logger) podName3 := "test3" acc4 := account.New(logger) @@ -73,7 +77,7 @@ func TestShare(t *testing.T) { t.Fatal(err) } fd4 := feed.New(acc4.GetUserAccountInfo(), mockClient, logger) - pod4 := pod.NewPod(mockClient, fd4, acc4, tm, logger) + pod4 := pod.NewPod(mockClient, fd4, acc4, tm, sm, logger) podName4 := "test4" acc5 := account.New(logger) @@ -82,7 +86,7 @@ func TestShare(t *testing.T) { t.Fatal(err) } fd5 := feed.New(acc5.GetUserAccountInfo(), mockClient, logger) - pod5 := pod.NewPod(mockClient, fd5, acc5, tm, logger) + pod5 := pod.NewPod(mockClient, fd5, acc5, tm, sm, logger) podName5 := "test5" acc6 := account.New(logger) @@ -91,7 +95,7 @@ func TestShare(t *testing.T) { t.Fatal(err) } fd6 := feed.New(acc6.GetUserAccountInfo(), mockClient, logger) - pod6 := pod.NewPod(mockClient, fd6, acc6, tm, logger) + pod6 := pod.NewPod(mockClient, fd6, acc6, tm, sm, logger) podName6 := "test6" t.Run("share-pod", func(t *testing.T) { @@ -416,7 +420,7 @@ func TestShare(t *testing.T) { t.Fatal(err) } fd7 := feed.New(acc7.GetUserAccountInfo(), mockClient, logger) - pod7 := pod.NewPod(mockClient, fd7, acc7, tm, logger) + pod7 := pod.NewPod(mockClient, fd7, acc7, tm, sm, logger) podName7 := "test7" acc8 := account.New(logger) @@ -425,7 +429,7 @@ func TestShare(t *testing.T) { t.Fatal(err) } fd8 := feed.New(acc8.GetUserAccountInfo(), mockClient, logger) - pod8 := pod.NewPod(mockClient, fd8, acc8, tm, logger) + pod8 := pod.NewPod(mockClient, fd8, acc8, tm, sm, logger) // create sending pod and receiving pod podPassword, _ := utils.GetRandString(pod.PasswordLength) @@ -493,11 +497,11 @@ func TestShare(t *testing.T) { t.Fatal(err) } dirObject8 := gotSharedPodInfo.GetDirectory() - dirInode1 := dirObject8.GetDirFromDirectoryMap("/parentDir/subDir1") + dirInode1 := dirObject8.GetInode(podPassword, "/parentDir/subDir1") if dirInode1 != nil { t.Fatalf("invalid dir entry") } - dirInode1 = dirObject8.GetDirFromDirectoryMap("/parentDir/newSubDir1") + dirInode1 = dirObject8.GetInode(podPassword, "/parentDir/newSubDir1") if dirInode1 == nil { t.Fatalf("invalid dir entry") } @@ -507,7 +511,7 @@ func TestShare(t *testing.T) { if dirInode1.Meta.Name != "newSubDir1" { t.Fatalf("invalid dir entry") } - dirInode2 := dirObject8.GetDirFromDirectoryMap("/parentDir/subDir2") + dirInode2 := dirObject8.GetInode(podPassword, "/parentDir/subDir2") if dirInode2 == nil { t.Fatalf("invalid dir entry") } @@ -519,11 +523,11 @@ func TestShare(t *testing.T) { } fileObject8 := gotInfo.GetFile() - fileMeta1 := fileObject8.GetFromFileMap("/parentDir/file1") + fileMeta1 := fileObject8.GetInode(podPassword, "/parentDir/file1") if fileMeta1 != nil { t.Fatalf("invalid file meta") } - fileMeta1 = fileObject8.GetFromFileMap("/parentDir/renamedFile1") + fileMeta1 = fileObject8.GetInode(podPassword, "/parentDir/renamedFile1") if fileMeta1 == nil { t.Fatalf("invalid file meta") } @@ -539,7 +543,7 @@ func TestShare(t *testing.T) { if fileMeta1.BlockSize != uint32(10) { t.Fatalf("invalid block size") } - fileMeta2 := fileObject.GetFromFileMap("/parentDir/file2") + fileMeta2 := fileObject.GetInode(podPassword, "/parentDir/file2") if fileMeta2 == nil { t.Fatalf("invalid file meta") } diff --git a/pkg/test/pod_stat_test.go b/pkg/test/pod_stat_test.go index a7d87971..c3555a2d 100644 --- a/pkg/test/pod_stat_test.go +++ b/pkg/test/pod_stat_test.go @@ -23,6 +23,8 @@ import ( "testing" "time" + mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/plexsysio/taskmanager" @@ -47,7 +49,9 @@ func TestStat(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() - pod1 := pod.NewPod(mockClient, fd, acc, tm, logger) + sm := mock3.NewMockSubscriptionManager() + + pod1 := pod.NewPod(mockClient, fd, acc, tm, sm, logger) podName1 := "test1" t.Run("pod-stat", func(t *testing.T) { diff --git a/pkg/test/stat_test.go b/pkg/test/stat_test.go index dc2302f2..7d615166 100644 --- a/pkg/test/stat_test.go +++ b/pkg/test/stat_test.go @@ -23,6 +23,8 @@ import ( "testing" "time" + mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/user" "github.com/plexsysio/taskmanager" @@ -39,6 +41,7 @@ func TestUserStat(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock3.NewMockSubscriptionManager() t.Run("stat-nonexistent-user", func(t *testing.T) { ens := mock2.NewMockNamespaceManager() @@ -56,7 +59,7 @@ func TestUserStat(t *testing.T) { ens := mock2.NewMockNamespaceManager() // create user userObject := user.NewUsers(mockClient, ens, logger) - _, _, _, _, ui, err := userObject.CreateNewUserV2("user1", "password1twelve", "", "", tm) + _, _, _, _, ui, err := userObject.CreateNewUserV2("user1", "password1twelve", "", "", tm, sm) if err != nil { t.Fatal(err) } diff --git a/pkg/test/subscription_test.go b/pkg/test/subscription_test.go new file mode 100644 index 00000000..7e4ec857 --- /dev/null +++ b/pkg/test/subscription_test.go @@ -0,0 +1,188 @@ +package test_test + +import ( + "context" + "os" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/fairdatasociety/fairOS-dfs/pkg/account" + "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/feed" + "github.com/fairdatasociety/fairOS-dfs/pkg/logging" + "github.com/fairdatasociety/fairOS-dfs/pkg/pod" + mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" + "github.com/plexsysio/taskmanager" + "github.com/stretchr/testify/assert" + goens "github.com/wealdtech/go-ens/v3" +) + +func TestSubscription(t *testing.T) { + mockClient := mock.NewMockBeeClient() + + logger := logging.New(os.Stdout, 0) + acc1 := account.New(logger) + _, _, err := acc1.CreateUserAccount("") + if err != nil { + t.Fatal(err) + } + fd := feed.New(acc1.GetUserAccountInfo(), mockClient, logger) + tm := taskmanager.New(1, 10, time.Second*15, logger) + defer func() { + _ = tm.Stop(context.Background()) + }() + addr1 := common.HexToAddress(acc1.GetUserAccountInfo().GetAddress().Hex()) + nameHash1, err := goens.NameHash(addr1.Hex()) + if err != nil { + t.Fatal(err) + } + + sm := mock2.NewMockSubscriptionManager() + pod1 := pod.NewPod(mockClient, fd, acc1, tm, sm, logger) + + randomLongPodName1, err := utils.GetRandString(64) + if err != nil { + t.Fatalf("error creating pod %s", randomLongPodName1) + } + + podPassword, _ := utils.GetRandString(pod.PasswordLength) + p1, err := pod1.CreatePod(randomLongPodName1, "", podPassword) + if err != nil { + t.Fatal(err) + } + + // make root dir so that other directories can be added + err = p1.GetDirectory().MkRootDir(randomLongPodName1, podPassword, p1.GetPodAddress(), p1.GetFeed()) + if err != nil { + t.Fatal(err) + } + + // create some dir and files + addFilesAndDirectories(t, p1, pod1, randomLongPodName1, podPassword) + p1, err = pod1.OpenPod(randomLongPodName1) + if err != nil { + t.Fatal(err) + } + category := [32]byte{} + err = pod1.ListPodInMarketplace(randomLongPodName1, randomLongPodName1, randomLongPodName1, "", 1, 10, category, nameHash1) + if err != nil { + t.Fatal(err) + } + + // sub + market, err := sm.GetAllSubscribablePods() + if err != nil { + t.Fatal(err) + } + + acc2 := account.New(logger) + _, _, err = acc2.CreateUserAccount("") + if err != nil { + t.Fatal(err) + } + + fd2 := feed.New(acc2.GetUserAccountInfo(), mockClient, logger) + pod2 := pod.NewPod(mockClient, fd2, acc2, tm, sm, logger) + addr2 := common.HexToAddress(acc2.GetUserAccountInfo().GetAddress().Hex()) + nameHash2, err := goens.NameHash(addr2.Hex()) + if err != nil { + t.Fatal(err) + } + err = pod2.RequestSubscription(market[0].SubHash, nameHash2) + if err != nil { + t.Fatal(err) + } + + requests, err := sm.GetSubRequests(addr1) + if err != nil { + t.Fatal(err) + } + + if requests[0].SubHash != market[0].SubHash { + t.Fatal("subhash mismatch") + } + + err = pod1.ApproveSubscription(p1.GetPodName(), requests[0].RequestHash, acc2.GetUserAccountInfo().GetPublicKey()) + if err != nil { + t.Fatal(err) + } + + subs, err := pod2.GetSubscriptions(requests[0].FdpBuyerNameHash) + if err != nil { + t.Fatal(err) + } + + podInfo, err := pod2.GetSubscribablePodInfo(subs[0].SubHash) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, len(subs), 1) + assert.Equal(t, podInfo.PodName, randomLongPodName1) + + pi, err := pod2.OpenSubscribedPod(subs[0].UnlockKeyLocation[:], acc1.GetUserAccountInfo().GetPublicKey()) + if err != nil { + t.Fatal("failed to open subscribed pod") + } + + dirObject := pi.GetDirectory() + + dirInode1 := dirObject.GetDirFromDirectoryMap("/parentDir/subDir1") + if dirInode1 == nil { + t.Fatalf("invalid dir entry") + } + + if dirInode1.Meta.Path != "/parentDir" { + t.Fatalf("invalid path entry") + } + if dirInode1.Meta.Name != "subDir1" { + t.Fatalf("invalid dir entry") + } + dirInode2 := dirObject.GetDirFromDirectoryMap("/parentDir/subDir2") + if dirInode2 == nil { + t.Fatalf("invalid dir entry") + } + if dirInode2.Meta.Path != "/parentDir" { + t.Fatalf("invalid path entry") + } + if dirInode2.Meta.Name != "subDir2" { + t.Fatalf("invalid dir entry") + } + + fileObject := pi.GetFile() + fileMeta1 := fileObject.GetInode(podPassword, "/parentDir/file1") + if fileMeta1 == nil { + t.Fatalf("invalid file meta") + } + + if fileMeta1.Path != "/parentDir" { + t.Fatalf("invalid path entry") + } + if fileMeta1.Name != "file1" { + t.Fatalf("invalid file entry") + } + if fileMeta1.Size != uint64(100) { + t.Fatalf("invalid file size") + } + if fileMeta1.BlockSize != uint32(10) { + t.Fatalf("invalid block size") + } + fileMeta2 := fileObject.GetInode(podPassword, "/parentDir/file2") + if fileMeta2 == nil { + t.Fatalf("invalid file meta") + } + if fileMeta2.Path != "/parentDir" { + t.Fatalf("invalid path entry") + } + if fileMeta2.Name != "file2" { + t.Fatalf("invalid file entry") + } + if fileMeta2.Size != uint64(200) { + t.Fatalf("invalid file size") + } + if fileMeta2.BlockSize != uint32(20) { + t.Fatalf("invalid block size") + } + +} diff --git a/pkg/test/sync_test.go b/pkg/test/sync_test.go index f7ea48cc..75cee66f 100644 --- a/pkg/test/sync_test.go +++ b/pkg/test/sync_test.go @@ -22,6 +22,8 @@ import ( "testing" "time" + mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/account" "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" @@ -43,8 +45,10 @@ func TestSync(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock2.NewMockSubscriptionManager() + fd := feed.New(acc.GetUserAccountInfo(), mockClient, logger) - pod1 := pod.NewPod(mockClient, fd, acc, tm, logger) + pod1 := pod.NewPod(mockClient, fd, acc, tm, sm, logger) podName1 := "test1" t.Run("sync-pod", func(t *testing.T) { @@ -76,7 +80,7 @@ func TestSync(t *testing.T) { // validate if the directory and files are synced dirObject := gotInfo.GetDirectory() - dirInode1 := dirObject.GetDirFromDirectoryMap("/parentDir/subDir1") + dirInode1 := dirObject.GetInode(podPassword, "/parentDir/subDir1") if dirInode1 == nil { t.Fatalf("invalid dir entry") } @@ -86,7 +90,7 @@ func TestSync(t *testing.T) { if dirInode1.Meta.Name != "subDir1" { t.Fatalf("invalid dir entry") } - dirInode2 := dirObject.GetDirFromDirectoryMap("/parentDir/subDir2") + dirInode2 := dirObject.GetInode(podPassword, "/parentDir/subDir2") if dirInode2 == nil { t.Fatalf("invalid dir entry") } @@ -98,7 +102,7 @@ func TestSync(t *testing.T) { } fileObject := gotInfo.GetFile() - fileMeta1 := fileObject.GetFromFileMap("/parentDir/file1") + fileMeta1 := fileObject.GetInode(podPassword, "/parentDir/file1") if fileMeta1 == nil { t.Fatalf("invalid file meta") } @@ -114,7 +118,7 @@ func TestSync(t *testing.T) { if fileMeta1.BlockSize != uint32(10) { t.Fatalf("invalid block size") } - fileMeta2 := fileObject.GetFromFileMap("/parentDir/file2") + fileMeta2 := fileObject.GetInode(podPassword, "/parentDir/file2") if fileMeta2 == nil { t.Fatalf("invalid file meta") } diff --git a/pkg/test/user_sharing_test.go b/pkg/test/user_sharing_test.go index 86253190..f5b0530b 100644 --- a/pkg/test/user_sharing_test.go +++ b/pkg/test/user_sharing_test.go @@ -24,6 +24,8 @@ import ( "testing" "time" + mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/fairdatasociety/fairOS-dfs/pkg/account" "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/ensm/eth/mock" @@ -53,9 +55,10 @@ func TestSharing(t *testing.T) { defer func() { _ = tm.Stop(context.Background()) }() + sm := mock3.NewMockSubscriptionManager() fd1 := feed.New(acc1.GetUserAccountInfo(), mockClient, logger) - pod1 := pod.NewPod(mockClient, fd1, acc1, tm, logger) + pod1 := pod.NewPod(mockClient, fd1, acc1, tm, sm, logger) podName1 := "test1" acc2 := account.New(logger) @@ -68,14 +71,14 @@ func TestSharing(t *testing.T) { t.Fatal(err) } fd2 := feed.New(acc2.GetUserAccountInfo(), mockClient, logger) - pod2 := pod.NewPod(mockClient, fd2, acc2, tm, logger) + pod2 := pod.NewPod(mockClient, fd2, acc2, tm, sm, logger) podName2 := "test2" t.Run("sharing-user", func(t *testing.T) { ens := mock2.NewMockNamespaceManager() // create source user userObject1 := user.NewUsers(mockClient, ens, logger) - _, _, _, _, ui0, err := userObject1.CreateNewUserV2("user1", "password1twelve", "", "", tm) + _, _, _, _, ui0, err := userObject1.CreateNewUserV2("user1", "password1twelve", "", "", tm, sm) if err != nil { t.Fatal(err) } @@ -95,7 +98,7 @@ func TestSharing(t *testing.T) { // create dir and file dirObject1 := info1.GetDirectory() - err = dirObject1.MkDir("/parentDir1", podPassword) + err = dirObject1.MkDir("/parentDir1", podPassword, 0) if err != nil { t.Fatal(err) } @@ -112,7 +115,7 @@ func TestSharing(t *testing.T) { // create destination user userObject2 := user.NewUsers(mockClient, ens, logger) - _, _, _, _, ui, err := userObject2.CreateNewUserV2("user2", "password1twelve", "", "", tm) + _, _, _, _, ui, err := userObject2.CreateNewUserV2("user2", "password1twelve", "", "", tm, sm) if err != nil { t.Fatal(err) } @@ -132,17 +135,13 @@ func TestSharing(t *testing.T) { // create dir and file dirObject2 := info2.GetDirectory() - err = dirObject2.MkDir("/parentDir2", podPassword) + err = dirObject2.MkDir("/parentDir2", podPassword, 0) if err != nil { t.Fatal(err) } // receive file info - sharingRef, err := utils.ParseSharingReference(sharingRefString) - if err != nil { - t.Fatal(err) - } - receiveFileInfo, err := userObject2.ReceiveFileInfo(sharingRef) + receiveFileInfo, err := userObject2.ReceiveFileInfo(sharingRefString) if err != nil { t.Fatal(err) } @@ -161,18 +160,18 @@ func TestSharing(t *testing.T) { t.Fatalf("invalid block size received") } - _, err = userObject2.ReceiveFileFromUser("podName2", sharingRef, ui, pod2, "/parentDir2") - if !errors.Is(err, pod.ErrPodNotOpened) { - t.Fatal("pod does not supposed tp be open") + _, err = userObject2.ReceiveFileFromUser("podName2", sharingRefString, ui, pod2, "/parentDir2") + if err == nil { + t.Fatal("pod should not exist") } // receive file - destinationFilePath, err := userObject2.ReceiveFileFromUser(podName2, sharingRef, ui, pod2, "/parentDir2") + destinationFilePath, err := userObject2.ReceiveFileFromUser(podName2, sharingRefString, ui, pod2, "/parentDir2") if err != nil { t.Fatal(err) } - _, err = userObject2.ReceiveFileFromUser(podName2, sharingRef, ui, pod2, "/parentDir2") + _, err = userObject2.ReceiveFileFromUser(podName2, sharingRefString, ui, pod2, "/parentDir2") if !errors.Is(err, file.ErrFileAlreadyPresent) { t.Fatal("pod does not supposed tp be open") } @@ -194,17 +193,11 @@ func TestSharing(t *testing.T) { if files[0] != "/parentDir2/file1" { t.Fatalf("file not imported") } - if !ui0.IsPodOpen(podName1) { - t.Fatalf("pod should be open") - } // delete source pod err = pod1.DeleteOwnPod(podName1) if err != nil { t.Fatalf("error deleting pod %s", podName1) } ui0.RemovePodName(podName1) - if ui0.IsPodOpen(podName1) { - t.Fatalf("pod should have been deleted") - } }) } diff --git a/pkg/user/ensInfo.go b/pkg/user/ensInfo.go new file mode 100644 index 00000000..2a262afa --- /dev/null +++ b/pkg/user/ensInfo.go @@ -0,0 +1,16 @@ +package user + +import ( + "crypto/ecdsa" + + "github.com/ethereum/go-ethereum/common" +) + +func (u *Users) GetUserInfoFromENS(nameHash [32]byte) (common.Address, *ecdsa.PublicKey, error) { + addr, publicKey, _, err := u.ens.GetInfoFromNameHash(nameHash) + return addr, publicKey, err +} + +func (u *Users) GetNameHash(username string) ([32]byte, error) { + return u.ens.GetNameHash(username) +} diff --git a/pkg/user/info.go b/pkg/user/info.go index 3bec76be..6e550401 100644 --- a/pkg/user/info.go +++ b/pkg/user/info.go @@ -78,16 +78,6 @@ func (i *Info) RemovePodName(podName string) { delete(i.openPods, podName) } -// IsPodOpen checks if users pod is open -func (i *Info) IsPodOpen(podName string) bool { - i.openPodsMu.RLock() - defer i.openPodsMu.RUnlock() - if _, ok := i.openPods[podName]; ok { - return true - } - return false -} - // GetUserDirectory returns user directory handler func (i *Info) GetUserDirectory() *d.Directory { return i.dir diff --git a/pkg/user/lite.go b/pkg/user/lite.go index 53898715..b447f40b 100644 --- a/pkg/user/lite.go +++ b/pkg/user/lite.go @@ -3,6 +3,8 @@ package user import ( "sync" + "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/fairdatasociety/fairOS-dfs/pkg/account" @@ -16,7 +18,7 @@ import ( // LoadLiteUser creates an off chain user, that has no ens or soc in the swarm. // It only creates the required information to execute user function and stores it in memory. -func (u *Users) LoadLiteUser(userName, _, mnemonic, sessionId string, tm taskmanager.TaskManagerGO) (string, string, *Info, error) { +func (u *Users) LoadLiteUser(userName, _, mnemonic, sessionId string, tm taskmanager.TaskManagerGO, sm subscriptionManager.SubscriptionManager) (string, string, *Info, error) { if !isUserNameValid(userName) { return "", "", nil, ErrInvalidUserName } @@ -33,7 +35,7 @@ func (u *Users) LoadLiteUser(userName, _, mnemonic, sessionId string, tm taskman // Instantiate pod, dir & file objects file := f.NewFile(userName, u.client, fd, accountInfo.GetAddress(), tm, u.logger) dir := d.NewDirectory(userName, u.client, fd, accountInfo.GetAddress(), file, tm, u.logger) - pod := p.NewPod(u.client, fd, acc, tm, u.logger) + pod := p.NewPod(u.client, fd, acc, tm, sm, u.logger) if sessionId == "" { sessionId = cookie.GetUniqueSessionId() } diff --git a/pkg/user/login.go b/pkg/user/login.go index 95c23e73..0307191a 100644 --- a/pkg/user/login.go +++ b/pkg/user/login.go @@ -17,8 +17,13 @@ limitations under the License. package user import ( + "fmt" "sync" + "github.com/ethereum/go-ethereum/common" + + "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager" + "github.com/fairdatasociety/fairOS-dfs/pkg/taskmanager" "github.com/ethereum/go-ethereum/crypto" @@ -34,7 +39,7 @@ import ( // LoginUserV2 checks if the user is present and logs in the user. It also creates the required information // to execute user function and stores it in memory. -func (u *Users) LoginUserV2(userName, passPhrase string, client blockstore.Client, tm taskmanager.TaskManagerGO, sessionId string) (*Info, string, string, error) { +func (u *Users) LoginUserV2(userName, passPhrase string, client blockstore.Client, tm taskmanager.TaskManagerGO, sm subscriptionManager.SubscriptionManager, sessionId string) (*Info, string, string, error) { // check if username is available (user created) if !u.IsUsernameAvailableV2(userName) { return nil, "", "", ErrUserNameNotFound @@ -61,6 +66,9 @@ func (u *Users) LoginUserV2(userName, passPhrase string, client blockstore.Clien if err != nil { // skipcq: TCV-001 return nil, "", "", err } + if publicKey == nil { + return nil, "", "", fmt.Errorf("public key not found") + } pb := crypto.FromECDSAPub(publicKey) // decrypt and remove pad from private ley @@ -69,6 +77,7 @@ func (u *Users) LoginUserV2(userName, passPhrase string, client blockstore.Clien return nil, "", "", err } // load user account + err = acc.LoadUserAccountFromSeed(seed) if err != nil { // skipcq: TCV-001 return nil, "", "", err @@ -80,7 +89,7 @@ func (u *Users) LoginUserV2(userName, passPhrase string, client blockstore.Clien // Instantiate pod, dir & file objects file := f.NewFile(userName, client, fd, accountInfo.GetAddress(), tm, u.logger) - pod := p.NewPod(u.client, fd, acc, tm, u.logger) + pod := p.NewPod(u.client, fd, acc, tm, sm, u.logger) dir := d.NewDirectory(userName, client, fd, accountInfo.GetAddress(), file, tm, u.logger) if sessionId == "" { sessionId = cookie.GetUniqueSessionId() @@ -133,3 +142,106 @@ func (u *Users) GetLoggedInUserInfo(sessionId string) *Info { func (u *Users) IsUserNameLoggedIn(userName string) bool { return u.isUserNameInMap(userName) } + +// ConnectWallet connects user with wallet. +func (u *Users) ConnectWallet(userName, passPhrase, walletAddressHex, signature string, client blockstore.Client) error { + // check if username is available (user created) + if !u.IsUsernameAvailableV2(userName) { + return ErrUserNameNotFound + } + + // get owner address from Subdomain registrar + address, err := u.ens.GetOwner(userName) + if err != nil { // skipcq: TCV-001 + return err + } + + // check if address matches with wallet address + if address.Hex() != walletAddressHex { + return fmt.Errorf("wallet doesnot match portable account address") + } + // create account + acc := account.New(u.logger) + accountInfo := acc.GetUserAccountInfo() + // load encrypted private key + fd := feed.New(accountInfo, client, u.logger) + key, err := u.downloadPortableAccount(utils.Address(address), userName, passPhrase, fd) + if err != nil { + u.logger.Errorf(err.Error()) + return err + } + + // decrypt and remove pad from private ley + seed, err := accountInfo.RemovePadFromSeed(key, passPhrase) + if err != nil { // skipcq: TCV-001 + return err + } + + if err = acc.LoadUserAccountFromSeed(seed); err != nil { + return err + } + + key, err = accountInfo.PadSeedName(seed, userName, signature) + if err != nil { // skipcq: TCV-001 + return err + } + return u.uploadPortableAccount(accountInfo, walletAddressHex, signature, key, fd) +} + +// LoginWithWallet logs user in with wallet and signature +func (u *Users) LoginWithWallet(addressHex, signature string, client blockstore.Client, tm taskmanager.TaskManagerGO, sm subscriptionManager.SubscriptionManager, sessionId string) (*Info, string, error) { + + address := common.HexToAddress(addressHex) + // create account + + acc := account.New(u.logger) + accountInfo := acc.GetUserAccountInfo() + // load encrypted private key + fd := feed.New(accountInfo, client, u.logger) + key, err := u.downloadPortableAccount(utils.Address(address), addressHex, signature, fd) + if err != nil { + u.logger.Errorf(err.Error()) + return nil, "", ErrInvalidPassword + } + + // decrypt and remove pad from private ley + seed, username, err := accountInfo.RemovePadFromSeedName(key, signature) + if err != nil { // skipcq: TCV-001 + return nil, "", err + } + + nameHash, err := u.GetNameHash(username) + if err != nil { // skipcq: TCV-001 + return nil, "", err + } + // load user account + err = acc.LoadUserAccountFromSeed(seed) + if err != nil { // skipcq: TCV-001 + return nil, "", err + } + + if u.IsUserLoggedIn(sessionId) { // skipcq: TCV-001 + return nil, "", ErrUserAlreadyLoggedIn + } + + // Instantiate pod, dir & file objects + file := f.NewFile(addressHex, client, fd, accountInfo.GetAddress(), tm, u.logger) + pod := p.NewPod(u.client, fd, acc, tm, sm, u.logger) + dir := d.NewDirectory(addressHex, client, fd, accountInfo.GetAddress(), file, tm, u.logger) + if sessionId == "" { + sessionId = cookie.GetUniqueSessionId() + } + ui := &Info{ + name: username, + sessionId: sessionId, + feedApi: fd, + account: acc, + file: file, + dir: dir, + pod: pod, + openPods: make(map[string]*p.Info), + openPodsMu: &sync.RWMutex{}, + } + // set cookie and add user to map + return ui, utils.Encode(nameHash[:]), u.addUserAndSessionToMap(ui) +} diff --git a/pkg/user/new.go b/pkg/user/new.go index de555f21..02340b0e 100644 --- a/pkg/user/new.go +++ b/pkg/user/new.go @@ -20,6 +20,8 @@ import ( "regexp" "sync" + "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager" + "github.com/fairdatasociety/fairOS-dfs/pkg/taskmanager" "github.com/ethereum/go-ethereum/common" @@ -41,7 +43,7 @@ const ( // CreateNewUserV2 creates a new user with the given username and password. if a mnemonic is passed // then it is used instead of creating a new one. -func (u *Users) CreateNewUserV2(userName, passPhrase, mnemonic, sessionId string, tm taskmanager.TaskManagerGO) (string, string, string, string, *Info, error) { +func (u *Users) CreateNewUserV2(userName, passPhrase, mnemonic, sessionId string, tm taskmanager.TaskManagerGO, sm subscriptionManager.SubscriptionManager) (string, string, string, string, *Info, error) { if userName == "" { return "", "", "", "", nil, ErrBlankUsername } @@ -102,7 +104,7 @@ func (u *Users) CreateNewUserV2(userName, passPhrase, mnemonic, sessionId string // Instantiate pod, dir & file objects file := f.NewFile(userName, u.client, fd, accountInfo.GetAddress(), tm, u.logger) dir := d.NewDirectory(userName, u.client, fd, accountInfo.GetAddress(), file, tm, u.logger) - pod := p.NewPod(u.client, fd, acc, tm, u.logger) + pod := p.NewPod(u.client, fd, acc, tm, sm, u.logger) if sessionId == "" { sessionId = cookie.GetUniqueSessionId() } diff --git a/pkg/user/sharing.go b/pkg/user/sharing.go index 0a4bd80f..3357d57f 100644 --- a/pkg/user/sharing.go +++ b/pkg/user/sharing.go @@ -17,13 +17,12 @@ limitations under the License. package user import ( + "encoding/hex" "encoding/json" "net/http" "strconv" "time" - "github.com/btcsuite/btcd/btcec" - "github.com/fairdatasociety/fairOS-dfs/pkg/account" f "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" @@ -89,53 +88,35 @@ func (u *Users) ShareFileWithUser(podName, podPassword, podFileWithPath, destina return "", err } - // encrypt data - encryptedData, err := encryptData(data, now.Unix()) - if err != nil { // skipcq: TCV-001 - return "", err - } - // upload the encrypted data and get the reference - ref, err := u.client.UploadBlob(encryptedData, 0, true, true) + ref, err := u.client.UploadBlob(data, 0, true) if err != nil { // skipcq: TCV-001 return "", err } - // add now to the ref - sharingRef := utils.NewSharingReference(ref, now.Unix()) - return sharingRef.String(), nil + return hex.EncodeToString(ref), nil } // ReceiveFileFromUser imports an exported file in to the current user and pod by reading the sharing file entry. -func (u *Users) ReceiveFileFromUser(podName string, sharingRef utils.SharingReference, userInfo *Info, pd *pod.Pod, podDir string) (string, error) { - metaRef := sharingRef.GetRef() - unixTime := sharingRef.GetNonce() - +func (u *Users) ReceiveFileFromUser(podName string, ref string, userInfo *Info, pd *pod.Pod, podDir string) (string, error) { + refBytes, err := hex.DecodeString(ref) + if err != nil { + return "", err + } // get the encrypted meta - encryptedData, respCode, err := u.client.DownloadBlob(metaRef) + data, respCode, err := u.client.DownloadBlob(refBytes) if err != nil || respCode != http.StatusOK { return "", err } // skipcq: TCV-001 - // decrypt the data - decryptedData, err := decryptData(encryptedData, unixTime) - if err != nil { // skipcq: TCV-001 - return "", err - } - // unmarshall the entry sharingEntry := SharingEntry{} - err = json.Unmarshal(decryptedData, &sharingEntry) + err = json.Unmarshal(data, &sharingEntry) if err != nil { // skipcq: TCV-001 return "", err } - // check if pod is open - if !pd.IsPodOpened(podName) { - return "", pod.ErrPodNotOpened - } - - podInfo, _, err := pd.GetPodInfoFromPodMap(podName) + podInfo, _, err := pd.GetPodInfo(podName) if err != nil { // skipcq: TCV-001 return "", err } @@ -146,7 +127,7 @@ func (u *Users) ReceiveFileFromUser(podName string, sharingRef utils.SharingRefe totalPath := utils.CombinePathAndFile(podDir, fileNameToAdd) // check if file is already present - if file.IsFileAlreadyPresent(totalPath) { + if file.IsFileAlreadyPresent(podInfo.GetPodPassword(), totalPath) { return "", f.ErrFileAlreadyPresent } @@ -179,45 +160,23 @@ func (u *Users) ReceiveFileFromUser(podName string, sharingRef utils.SharingRefe return totalPath, nil } -func encryptData(data []byte, now int64) ([]byte, error) { - pk, err := account.CreateRandomKeyPair(now) - if err != nil { // skipcq: TCV-001 - return nil, err - } - pubKey := btcec.PublicKey{Curve: pk.PublicKey.Curve, X: pk.PublicKey.X, Y: pk.PublicKey.Y} - return btcec.Encrypt(&pubKey, data) -} - -func decryptData(data []byte, now int64) ([]byte, error) { - pk, err := account.CreateRandomKeyPair(now) - if err != nil { // skipcq: TCV-001 - return nil, err - } - privateKey := btcec.PrivateKey{PublicKey: pk.PublicKey, D: pk.D} - return btcec.Decrypt(&privateKey, data) -} - // ReceiveFileInfo displays the information of the exported file. This is used to decide whether // to import the file or not. -func (u *Users) ReceiveFileInfo(sharingRef utils.SharingReference) (*ReceiveFileInfo, error) { - metaRef := sharingRef.GetRef() - unixTime := sharingRef.GetNonce() - - // get the encrypted meta - encryptedData, respCode, err := u.client.DownloadBlob(metaRef) - if err != nil || respCode != http.StatusOK { // skipcq: TCV-001 +func (u *Users) ReceiveFileInfo(ref string) (*ReceiveFileInfo, error) { + refBytes, err := hex.DecodeString(ref) + if err != nil { return nil, err } - // decrypt the data - decryptedData, err := decryptData(encryptedData, unixTime) - if err != nil { // skipcq: TCV-001 + // get the encrypted meta + data, respCode, err := u.client.DownloadBlob(refBytes) + if err != nil || respCode != http.StatusOK { // skipcq: TCV-001 return nil, err } // unmarshall the entry sharingEntry := SharingEntry{} - err = json.Unmarshal(decryptedData, &sharingEntry) + err = json.Unmarshal(data, &sharingEntry) if err != nil { // skipcq: TCV-001 return nil, err } diff --git a/swagger/docs.go b/swagger/docs.go index 953b9679..3afcb6de 100644 --- a/swagger/docs.go +++ b/swagger/docs.go @@ -20,6 +20,207 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/public-dir": { + "get": { + "description": "PublicPodGetDirHandler is the api handler to list content of a directory from a public pod", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "public" + ], + "summary": "List directory content", + "parameters": [ + { + "type": "string", + "description": "pod sharing reference", + "name": "sharingRef", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "dir location in the pod", + "name": "dirPath", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.ListFileResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/public-file": { + "get": { + "description": "PodReceiveInfoHandler is the api handler to download file from a shared pod", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "public" + ], + "summary": "download file from a shared pod", + "parameters": [ + { + "type": "string", + "description": "pod sharing reference", + "name": "sharingRef", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "file location in the pod", + "name": "filePath", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/public-kv": { + "get": { + "description": "PublicPodKVEntryGetHandler is the api handler to get key from key value store from a public pod", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "public" + ], + "summary": "get key from public pod", + "parameters": [ + { + "type": "string", + "description": "pod sharing reference", + "name": "sharingRef", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "table name", + "name": "tableName", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "key to look up", + "name": "key", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.KVResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/public/{ref}/{file}": { + "get": { + "description": "PublicPodFilePathHandler is the api handler to download file from a shared pod", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "public" + ], + "summary": "download file from a shared pod", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, "/v1/dir/chmod": { "post": { "description": "DirectoryModeHandler is the api handler to change mode of a directory", @@ -2692,6 +2893,112 @@ const docTemplate = `{ } } }, + "/v1/pod/fork": { + "post": { + "description": "PodForkHandler is the api handler to fork a pod", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "pod" + ], + "summary": "Fork a pod", + "parameters": [ + { + "description": "pod name and user password", + "name": "pod_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.PodForkRequest" + } + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/v1/pod/fork-from-reference": { + "post": { + "description": "PodForkFromReferenceHandler is the api handler to fork a pod from a given sharing reference", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "pod" + ], + "summary": "Fork a pod from sharing reference", + "parameters": [ + { + "description": "pod name and user password", + "name": "pod_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.PodForkFromReferenceRequest" + } + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, "/v1/pod/ls": { "get": { "description": "PodListHandler is the api handler to list all pods", @@ -3298,7 +3605,7 @@ const docTemplate = `{ "parameters": [ { "type": "string", - "description": "user name", + "description": "username", "name": "userName", "in": "query", "required": true @@ -3494,7 +3801,7 @@ const docTemplate = `{ "summary": "Login User", "parameters": [ { - "description": "user name", + "description": "username", "name": "user_request", "in": "body", "required": true, @@ -3550,7 +3857,7 @@ const docTemplate = `{ "parameters": [ { "type": "string", - "description": "user name", + "description": "username", "name": "userName", "in": "query", "required": true @@ -3587,7 +3894,7 @@ const docTemplate = `{ "summary": "Register New User", "parameters": [ { - "description": "user name", + "description": "username", "name": "user_request", "in": "body", "required": true, @@ -3939,6 +4246,28 @@ const docTemplate = `{ } } }, + "api.PodForkFromReferenceRequest": { + "type": "object", + "properties": { + "forkName": { + "type": "string" + }, + "podSharingReference": { + "type": "string" + } + } + }, + "api.PodForkRequest": { + "type": "object", + "properties": { + "forkName": { + "type": "string" + }, + "podName": { + "type": "string" + } + } + }, "api.PodListResponse": { "type": "object", "properties": { @@ -4219,20 +4548,6 @@ const docTemplate = `{ } } }, - "file.Blocks": { - "type": "object", - "properties": { - "compressedSize": { - "type": "string" - }, - "reference": { - "type": "string" - }, - "size": { - "type": "string" - } - } - }, "file.Entry": { "type": "object", "properties": { @@ -4259,9 +4574,6 @@ const docTemplate = `{ }, "size": { "type": "string" - }, - "tag": { - "type": "integer" } } }, @@ -4274,12 +4586,6 @@ const docTemplate = `{ "blockSize": { "type": "string" }, - "blocks": { - "type": "array", - "items": { - "$ref": "#/definitions/file.Blocks" - } - }, "compression": { "type": "string" }, @@ -4306,9 +4612,6 @@ const docTemplate = `{ }, "podName": { "type": "string" - }, - "tag": { - "type": "integer" } } }, diff --git a/swagger/swagger.json b/swagger/swagger.json index 3a8a544d..ba21d0d3 100644 --- a/swagger/swagger.json +++ b/swagger/swagger.json @@ -11,6 +11,207 @@ "version": "v0.0.0" }, "paths": { + "/public-dir": { + "get": { + "description": "PublicPodGetDirHandler is the api handler to list content of a directory from a public pod", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "public" + ], + "summary": "List directory content", + "parameters": [ + { + "type": "string", + "description": "pod sharing reference", + "name": "sharingRef", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "dir location in the pod", + "name": "dirPath", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.ListFileResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/public-file": { + "get": { + "description": "PodReceiveInfoHandler is the api handler to download file from a shared pod", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "public" + ], + "summary": "download file from a shared pod", + "parameters": [ + { + "type": "string", + "description": "pod sharing reference", + "name": "sharingRef", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "file location in the pod", + "name": "filePath", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/public-kv": { + "get": { + "description": "PublicPodKVEntryGetHandler is the api handler to get key from key value store from a public pod", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "public" + ], + "summary": "get key from public pod", + "parameters": [ + { + "type": "string", + "description": "pod sharing reference", + "name": "sharingRef", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "table name", + "name": "tableName", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "key to look up", + "name": "key", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.KVResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/public/{ref}/{file}": { + "get": { + "description": "PublicPodFilePathHandler is the api handler to download file from a shared pod", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "public" + ], + "summary": "download file from a shared pod", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, "/v1/dir/chmod": { "post": { "description": "DirectoryModeHandler is the api handler to change mode of a directory", @@ -2683,6 +2884,112 @@ } } }, + "/v1/pod/fork": { + "post": { + "description": "PodForkHandler is the api handler to fork a pod", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "pod" + ], + "summary": "Fork a pod", + "parameters": [ + { + "description": "pod name and user password", + "name": "pod_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.PodForkRequest" + } + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/v1/pod/fork-from-reference": { + "post": { + "description": "PodForkFromReferenceHandler is the api handler to fork a pod from a given sharing reference", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "pod" + ], + "summary": "Fork a pod from sharing reference", + "parameters": [ + { + "description": "pod name and user password", + "name": "pod_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.PodForkFromReferenceRequest" + } + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, "/v1/pod/ls": { "get": { "description": "PodListHandler is the api handler to list all pods", @@ -3289,7 +3596,7 @@ "parameters": [ { "type": "string", - "description": "user name", + "description": "username", "name": "userName", "in": "query", "required": true @@ -3485,7 +3792,7 @@ "summary": "Login User", "parameters": [ { - "description": "user name", + "description": "username", "name": "user_request", "in": "body", "required": true, @@ -3541,7 +3848,7 @@ "parameters": [ { "type": "string", - "description": "user name", + "description": "username", "name": "userName", "in": "query", "required": true @@ -3578,7 +3885,7 @@ "summary": "Register New User", "parameters": [ { - "description": "user name", + "description": "username", "name": "user_request", "in": "body", "required": true, @@ -3930,6 +4237,28 @@ } } }, + "api.PodForkFromReferenceRequest": { + "type": "object", + "properties": { + "forkName": { + "type": "string" + }, + "podSharingReference": { + "type": "string" + } + } + }, + "api.PodForkRequest": { + "type": "object", + "properties": { + "forkName": { + "type": "string" + }, + "podName": { + "type": "string" + } + } + }, "api.PodListResponse": { "type": "object", "properties": { @@ -4210,20 +4539,6 @@ } } }, - "file.Blocks": { - "type": "object", - "properties": { - "compressedSize": { - "type": "string" - }, - "reference": { - "type": "string" - }, - "size": { - "type": "string" - } - } - }, "file.Entry": { "type": "object", "properties": { @@ -4250,9 +4565,6 @@ }, "size": { "type": "string" - }, - "tag": { - "type": "integer" } } }, @@ -4265,12 +4577,6 @@ "blockSize": { "type": "string" }, - "blocks": { - "type": "array", - "items": { - "$ref": "#/definitions/file.Blocks" - } - }, "compression": { "type": "string" }, @@ -4297,9 +4603,6 @@ }, "podName": { "type": "string" - }, - "tag": { - "type": "integer" } } }, diff --git a/swagger/swagger.yaml b/swagger/swagger.yaml index 48fc0b1c..63b7752d 100644 --- a/swagger/swagger.yaml +++ b/swagger/swagger.yaml @@ -200,6 +200,20 @@ definitions: loggedin: type: boolean type: object + api.PodForkFromReferenceRequest: + properties: + forkName: + type: string + podSharingReference: + type: string + type: object + api.PodForkRequest: + properties: + forkName: + type: string + podName: + type: string + type: object api.PodListResponse: properties: pods: @@ -380,15 +394,6 @@ definitions: podName: type: string type: object - file.Blocks: - properties: - compressedSize: - type: string - reference: - type: string - size: - type: string - type: object file.Entry: properties: accessTime: @@ -407,8 +412,6 @@ definitions: type: string size: type: string - tag: - type: integer type: object file.Stats: properties: @@ -416,10 +419,6 @@ definitions: type: string blockSize: type: string - blocks: - items: - $ref: '#/definitions/file.Blocks' - type: array compression: type: string contentType: @@ -438,8 +437,6 @@ definitions: type: string podName: type: string - tag: - type: integer type: object pod.ShareInfo: properties: @@ -491,6 +488,144 @@ info: title: FairOS-dfs server version: v0.0.0 paths: + /public-dir: + get: + consumes: + - application/json + description: PublicPodGetDirHandler is the api handler to list content of a + directory from a public pod + parameters: + - description: pod sharing reference + in: query + name: sharingRef + required: true + type: string + - description: dir location in the pod + in: query + name: dirPath + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.ListFileResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: List directory content + tags: + - public + /public-file: + get: + consumes: + - application/json + description: PodReceiveInfoHandler is the api handler to download file from + a shared pod + parameters: + - description: pod sharing reference + in: query + name: sharingRef + required: true + type: string + - description: file location in the pod + in: query + name: filePath + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + type: integer + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: download file from a shared pod + tags: + - public + /public-kv: + get: + consumes: + - application/json + description: PublicPodKVEntryGetHandler is the api handler to get key from key + value store from a public pod + parameters: + - description: pod sharing reference + in: query + name: sharingRef + required: true + type: string + - description: table name + in: query + name: tableName + required: true + type: string + - description: key to look up + in: query + name: key + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.KVResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: get key from public pod + tags: + - public + /public/{ref}/{file}: + get: + consumes: + - application/json + description: PublicPodFilePathHandler is the api handler to download file from + a shared pod + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + type: integer + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: download file from a shared pod + tags: + - public /v1/dir/chmod: post: consumes: @@ -2312,6 +2447,77 @@ paths: summary: Delete pod tags: - pod + /v1/pod/fork: + post: + consumes: + - application/json + description: PodForkHandler is the api handler to fork a pod + parameters: + - description: pod name and user password + in: body + name: pod_request + required: true + schema: + $ref: '#/definitions/api.PodForkRequest' + - description: cookie parameter + in: header + name: Cookie + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: Fork a pod + tags: + - pod + /v1/pod/fork-from-reference: + post: + consumes: + - application/json + description: PodForkFromReferenceHandler is the api handler to fork a pod from + a given sharing reference + parameters: + - description: pod name and user password + in: body + name: pod_request + required: true + schema: + $ref: '#/definitions/api.PodForkFromReferenceRequest' + - description: cookie parameter + in: header + name: Cookie + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: Fork a pod from sharing reference + tags: + - pod /v1/pod/ls: get: consumes: @@ -2711,7 +2917,7 @@ paths: - application/json description: Check if the given user is logged-in parameters: - - description: user name + - description: username in: query name: userName required: true @@ -2841,7 +3047,7 @@ paths: - application/json description: login user with the new ENS based authentication parameters: - - description: user name + - description: username in: body name: user_request required: true @@ -2877,7 +3083,7 @@ paths: get: description: checks if the new user is present in the new ENS based authentication parameters: - - description: user name + - description: username in: query name: userName required: true @@ -2902,7 +3108,7 @@ paths: - application/json description: registers new user with the new ENS based authentication parameters: - - description: user name + - description: username in: body name: user_request required: true diff --git a/wasm/main.go b/wasm/main.go index f679dabd..8c19b691 100644 --- a/wasm/main.go +++ b/wasm/main.go @@ -39,12 +39,17 @@ func registerWasmFunctions() { js.Global().Set("connect", js.FuncOf(connect)) js.Global().Set("stop", js.FuncOf(stop)) + js.Global().Set("publicKvEntryGet", js.FuncOf(publicKvEntryGet)) + + js.Global().Set("connectWallet", js.FuncOf(connectWallet)) js.Global().Set("login", js.FuncOf(login)) + js.Global().Set("walletLogin", js.FuncOf(walletLogin)) js.Global().Set("userPresent", js.FuncOf(userPresent)) js.Global().Set("userIsLoggedIn", js.FuncOf(userIsLoggedIn)) js.Global().Set("userLogout", js.FuncOf(userLogout)) js.Global().Set("userDelete", js.FuncOf(userDelete)) js.Global().Set("userStat", js.FuncOf(userStat)) + js.Global().Set("getNameHash", js.FuncOf(getNameHash)) js.Global().Set("podNew", js.FuncOf(podNew)) js.Global().Set("podOpen", js.FuncOf(podOpen)) @@ -57,6 +62,14 @@ func registerWasmFunctions() { js.Global().Set("podReceive", js.FuncOf(podReceive)) js.Global().Set("podReceiveInfo", js.FuncOf(podReceiveInfo)) + js.Global().Set("getSubscriptions", js.FuncOf(getSubscriptions)) + js.Global().Set("openSubscribedPod", js.FuncOf(openSubscribedPod)) + js.Global().Set("getSubscribablePods", js.FuncOf(getSubscribablePods)) + js.Global().Set("getSubRequests", js.FuncOf(getSubRequests)) + js.Global().Set("getSubscribablePodInfo", js.FuncOf(getSubscribablePodInfo)) + js.Global().Set("encryptSubscription", js.FuncOf(encryptSubscription)) + js.Global().Set("openSubscribedPodFromReference", js.FuncOf(openSubscribedPodFromReference)) + js.Global().Set("dirPresent", js.FuncOf(dirPresent)) js.Global().Set("dirMake", js.FuncOf(dirMake)) js.Global().Set("dirRemove", js.FuncOf(dirRemove)) @@ -101,22 +114,27 @@ func connect(_ js.Value, funcArgs []js.Value) interface{} { resolve := args[0] reject := args[1] if len(funcArgs) != 4 { - reject.Invoke("not enough arguments. \"connect(beeEndpoint, stampId, false, rpc, play)\"") + reject.Invoke("not enough arguments. \"connect(beeEndpoint, stampId, rpc, network)\"") return nil } beeEndpoint := funcArgs[0].String() stampId := funcArgs[1].String() rpc := funcArgs[2].String() network := funcArgs[3].String() + //subRpc := funcArgs[4].String() + //subContractAddress := funcArgs[5].String() if network != "testnet" && network != "play" { reject.Invoke("unknown network. \"use play or testnet\"") return nil } - var config *contracts.Config + var ( + config *contracts.ENSConfig + ) + if network == "play" { - config = contracts.PlayConfig() + config, _ = contracts.PlayConfig() } else { - config = contracts.TestnetConfig() + config, _ = contracts.TestnetConfig() } config.ProviderBackend = rpc logger := logging.New(os.Stdout, logrus.DebugLevel) @@ -127,6 +145,7 @@ func connect(_ js.Value, funcArgs []js.Value) interface{} { beeEndpoint, stampId, config, + nil, logger, ) if err != nil { @@ -147,6 +166,53 @@ func stop(js.Value, []js.Value) interface{} { return nil } +func publicKvEntryGet(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + + if len(funcArgs) != 3 { + reject.Invoke("not enough arguments. \"publicKvEntryGet(sharingRef, tableName, key)\"") + return nil + } + sharingRef := funcArgs[0].String() + tableName := funcArgs[1].String() + key := funcArgs[2].String() + + ref, err := utils.ParseHexReference(sharingRef) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod kv get: invalid reference: %s", err.Error())) + return nil + } + + go func() { + shareInfo, err := api.PublicPodReceiveInfo(ref) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod kv get: %v", err)) + return + } + columns, data, err := api.PublicPodKVEntryGet(shareInfo, tableName, key) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod kv get: %s", err.Error())) + return + } + var res KVResponse + if columns != nil { + res.Keys = columns + } else { + res.Keys = []string{key} + } + res.Values = data + resp, _ := json.Marshal(res) + resolve.Invoke(resp) + }() + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + func login(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] @@ -160,16 +226,82 @@ func login(_ js.Value, funcArgs []js.Value) interface{} { password := funcArgs[1].String() go func() { - ui, _, _, err := api.LoginUserV2(username, password, "") + ui, nameHash, _, err := api.LoginUserV2(username, password, "") if err != nil { reject.Invoke(fmt.Sprintf("Failed to create user : %s", err.Error())) return } - data := map[string]string{} - data["user"] = ui.GetUserName() - data["sessionId"] = ui.GetSessionId() - resp, _ := json.Marshal(data) - resolve.Invoke(string(resp)) + object := js.Global().Get("Object").New() + object.Set("user", ui.GetUserName()) + object.Set("address", ui.GetAccount().GetUserAccountInfo().GetAddress().Hex()) + object.Set("nameHash", nameHash) + object.Set("sessionId", ui.GetSessionId()) + + resolve.Invoke(object) + }() + + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + +func walletLogin(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + + if len(funcArgs) != 2 { + reject.Invoke("not enough arguments. \"walletLogin(addressHex, signature)\"") + return nil + } + address := funcArgs[0].String() + signature := funcArgs[1].String() + + go func() { + ui, nameHash, err := api.LoginWithWallet(address, signature, "") + if err != nil { + reject.Invoke(fmt.Sprintf("Failed to login user : %s", err.Error())) + return + } + + object := js.Global().Get("Object").New() + object.Set("user", ui.GetUserName()) + object.Set("address", ui.GetAccount().GetUserAccountInfo().GetAddress().Hex()) + object.Set("nameHash", nameHash) + object.Set("sessionId", ui.GetSessionId()) + resolve.Invoke(object) + }() + + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + +func connectWallet(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + + if len(funcArgs) != 4 { + reject.Invoke("not enough arguments. \"connectWallet(username, password, walletAddress, signature)\"") + return nil + } + username := funcArgs[0].String() + password := funcArgs[1].String() + walletAddress := funcArgs[2].String() + signature := funcArgs[3].String() + + go func() { + err := api.ConnectPortableAccountWithWallet(username, password, walletAddress, signature) + if err != nil { + reject.Invoke(fmt.Sprintf("Failed to create user : %s", err.Error())) + return + } + resolve.Invoke("wallet connected") }() return nil @@ -192,10 +324,10 @@ func userPresent(_ js.Value, funcArgs []js.Value) interface{} { go func() { present := api.IsUserNameAvailableV2(username) - data := map[string]bool{} - data["present"] = present - resp, _ := json.Marshal(data) - resolve.Invoke(string(resp)) + object := js.Global().Get("Object").New() + object.Set("present", present) + + resolve.Invoke(object) }() return nil }) @@ -217,10 +349,11 @@ func userIsLoggedIn(_ js.Value, funcArgs []js.Value) interface{} { go func() { loggedin := api.IsUserLoggedIn(username) - data := map[string]bool{} - data["loggedin"] = loggedin - resp, _ := json.Marshal(data) - resolve.Invoke(string(resp)) + + object := js.Global().Get("Object").New() + object.Set("loggedin", loggedin) + + resolve.Invoke(object) }() return nil }) @@ -299,8 +432,12 @@ func userStat(_ js.Value, funcArgs []js.Value) interface{} { reject.Invoke(fmt.Sprintf("userStat failed : %s", err.Error())) return } - data, _ := json.Marshal(stat) - resolve.Invoke(string(data)) + + object := js.Global().Get("Object").New() + object.Set("userName", stat.Name) + object.Set("address", stat.Reference) + + resolve.Invoke(object) }() return nil }) @@ -461,11 +598,22 @@ func podList(_ js.Value, funcArgs []js.Value) interface{} { reject.Invoke(fmt.Sprintf("podList failed : %s", err.Error())) return } - data := map[string]interface{}{} - data["pods"] = ownPods - data["sharedPods"] = sharedPods - resp, _ := json.Marshal(data) - resolve.Invoke(string(resp)) + + object := js.Global().Get("Object").New() + pods := js.Global().Get("Array").New(len(ownPods)) + for i, v := range ownPods { + pods.SetIndex(i, js.ValueOf(v)) + } + + sPods := js.Global().Get("Array").New(len(sharedPods)) + for i, v := range sharedPods { + sPods.SetIndex(i, js.ValueOf(v)) + } + + object.Set("pods", pods) + object.Set("sharedPods", sPods) + + resolve.Invoke(object) }() return nil }) @@ -492,8 +640,11 @@ func podStat(_ js.Value, funcArgs []js.Value) interface{} { reject.Invoke(fmt.Sprintf("podStat failed : %s", err.Error())) return } - resp, _ := json.Marshal(stat) - resolve.Invoke(string(resp)) + object := js.Global().Get("Object").New() + object.Set("podName", stat.PodName) + object.Set("address", stat.PodAddress) + + resolve.Invoke(object) }() return nil }) @@ -521,10 +672,10 @@ func podShare(_ js.Value, funcArgs []js.Value) interface{} { reject.Invoke(fmt.Sprintf("podShare failed : %s", err.Error())) return } - data := map[string]string{} - data["podSharingReference"] = reference - resp, _ := json.Marshal(data) - resolve.Invoke(string(resp)) + object := js.Global().Get("Object").New() + object.Set("podSharingReference", reference) + + resolve.Invoke(object) }() return nil }) @@ -589,8 +740,14 @@ func podReceiveInfo(_ js.Value, funcArgs []js.Value) interface{} { reject.Invoke(fmt.Sprintf("podReceiveInfo failed : %s", err.Error())) return } - resp, _ := json.Marshal(shareInfo) - resolve.Invoke(string(resp)) + + object := js.Global().Get("Object").New() + object.Set("podName", shareInfo.PodName) + object.Set("podAddress", shareInfo.Address) + object.Set("password", shareInfo.Password) + object.Set("userAddress", shareInfo.UserAddress) + + resolve.Invoke(object) }() return nil }) @@ -618,10 +775,11 @@ func dirPresent(_ js.Value, funcArgs []js.Value) interface{} { reject.Invoke(fmt.Sprintf("dirPresent failed : %s", err.Error())) return } - data := map[string]bool{} - data["present"] = present - resp, _ := json.Marshal(data) - resolve.Invoke(string(resp)) + + object := js.Global().Get("Object").New() + object.Set("present", present) + + resolve.Invoke(object) }() return nil }) @@ -644,7 +802,7 @@ func dirMake(_ js.Value, funcArgs []js.Value) interface{} { dirPath := funcArgs[2].String() go func() { - err := api.Mkdir(podName, dirPath, sessionId) + err := api.Mkdir(podName, dirPath, sessionId, 0) if err != nil { reject.Invoke(fmt.Sprintf("dirMake failed : %s", err.Error())) return @@ -705,11 +863,37 @@ func dirList(_ js.Value, funcArgs []js.Value) interface{} { reject.Invoke(fmt.Sprintf("dirList failed : %s", err.Error())) return } - data := map[string]interface{}{} - data["files"] = files - data["dirs"] = dirs - resp, _ := json.Marshal(data) - resolve.Invoke(string(resp)) + filesList := js.Global().Get("Array").New(len(files)) + for i, v := range files { + file := js.Global().Get("Object").New() + file.Set("name", v.Name) + file.Set("contentType", v.ContentType) + file.Set("size", v.Size) + file.Set("blockSize", v.BlockSize) + file.Set("creationTime", v.CreationTime) + file.Set("modificationTime", v.ModificationTime) + file.Set("accessTime", v.AccessTime) + file.Set("mode", v.Mode) + filesList.SetIndex(i, file) + } + dirsList := js.Global().Get("Array").New(len(dirs)) + for i, v := range dirs { + dir := js.Global().Get("Object").New() + dir.Set("name", v.Name) + dir.Set("contentType", v.ContentType) + dir.Set("size", v.Size) + dir.Set("mode", v.Mode) + dir.Set("blockSize", v.BlockSize) + dir.Set("creationTime", v.CreationTime) + dir.Set("modificationTime", v.ModificationTime) + dir.Set("accessTime", v.AccessTime) + dirsList.SetIndex(i, dir) + } + object := js.Global().Get("Object").New() + object.Set("files", filesList) + object.Set("dirs", dirsList) + + resolve.Invoke(object) }() return nil }) @@ -737,8 +921,18 @@ func dirStat(_ js.Value, funcArgs []js.Value) interface{} { reject.Invoke(fmt.Sprintf("dirStat failed : %s", err.Error())) return } - resp, _ := json.Marshal(stat) - resolve.Invoke(string(resp)) + object := js.Global().Get("Object").New() + object.Set("podName", stat.PodName) + object.Set("dirPath", stat.DirPath) + object.Set("dirName", stat.DirName) + object.Set("mode", stat.Mode) + object.Set("creationTime", stat.CreationTime) + object.Set("modificationTime", stat.ModificationTime) + object.Set("accessTime", stat.AccessTime) + object.Set("noOfDirectories", stat.NoOfDirectories) + object.Set("noOfFiles", stat.NoOfFiles) + + resolve.Invoke(object) }() return nil }) @@ -816,7 +1010,7 @@ func fileUpload(_ js.Value, funcArgs []js.Value) interface{} { js.CopyBytesToGo(inBuf, array) reader := bytes.NewReader(inBuf) - err := api.UploadFile(podName, fileName, sessionId, int64(size), reader, dirPath, compression, uint32(bs), true) + err := api.UploadFile(podName, fileName, sessionId, int64(size), reader, dirPath, compression, uint32(bs), 0, true) if err != nil { reject.Invoke(fmt.Sprintf("fileUpload failed : %s", err.Error())) return @@ -849,10 +1043,11 @@ func fileShare(_ js.Value, funcArgs []js.Value) interface{} { reject.Invoke(fmt.Sprintf("fileShare failed : %s", err.Error())) return } - data := map[string]string{} - data["fileSharingReference"] = ref - resp, _ := json.Marshal(data) - resolve.Invoke(string(resp)) + + object := js.Global().Get("Object").New() + object.Set("fileSharingReference", ref) + + resolve.Invoke(object) }() return nil }) @@ -876,20 +1071,15 @@ func fileReceive(_ js.Value, funcArgs []js.Value) interface{} { fileSharingReference := funcArgs[3].String() go func() { - ref, err := utils.ParseSharingReference(fileSharingReference) - if err != nil { - reject.Invoke(fmt.Sprintf("fileReceive failed : %s", err.Error())) - return - } - filePath, err := api.ReceiveFile(podName, sessionId, ref, directory) + filePath, err := api.ReceiveFile(podName, sessionId, fileSharingReference, directory) if err != nil { reject.Invoke(fmt.Sprintf("fileReceive failed : %s", err.Error())) return } - data := map[string]string{} - data["fileName"] = filePath - resp, _ := json.Marshal(data) - resolve.Invoke(string(resp)) + object := js.Global().Get("Object").New() + object.Set("fileName", filePath) + + resolve.Invoke(object) }() return nil }) @@ -911,18 +1101,23 @@ func fileReceiveInfo(_ js.Value, funcArgs []js.Value) interface{} { fileSharingReference := funcArgs[2].String() go func() { - ref, err := utils.ParseSharingReference(fileSharingReference) - if err != nil { - reject.Invoke(fmt.Sprintf("fileReceiveInfo failed : %s", err.Error())) - return - } - receiveInfo, err := api.ReceiveInfo(sessionId, ref) + receiveInfo, err := api.ReceiveInfo(sessionId, fileSharingReference) if err != nil { reject.Invoke(fmt.Sprintf("fileReceiveInfo failed : %s", err.Error())) return } - resp, _ := json.Marshal(receiveInfo) - resolve.Invoke(string(resp)) + object := js.Global().Get("Object").New() + object.Set("name", receiveInfo.FileName) + object.Set("size", receiveInfo.Size) + object.Set("blockSize", receiveInfo.BlockSize) + object.Set("numberOfBlocks", receiveInfo.NumberOfBlocks) + object.Set("contentType", receiveInfo.ContentType) + object.Set("compression", receiveInfo.Compression) + object.Set("sourceAddress", receiveInfo.Sender) + object.Set("destAddress", receiveInfo.Receiver) + object.Set("sharedTime", receiveInfo.SharedTime) + + resolve.Invoke(object) }() return nil }) @@ -978,8 +1173,20 @@ func fileStat(_ js.Value, funcArgs []js.Value) interface{} { reject.Invoke(fmt.Sprintf("fileStat failed : %s", err.Error())) return } - resp, _ := json.Marshal(stat) - resolve.Invoke(string(resp)) + object := js.Global().Get("Object").New() + object.Set("podName", stat.PodName) + object.Set("mode", stat.Mode) + object.Set("filePath", stat.FilePath) + object.Set("fileName", stat.FileName) + object.Set("fileSize", stat.FileSize) + object.Set("blockSize", stat.BlockSize) + object.Set("compression", stat.Compression) + object.Set("contentType", stat.ContentType) + object.Set("creationTime", stat.CreationTime) + object.Set("modificationTime", stat.ModificationTime) + object.Set("accessTime", stat.AccessTime) + + resolve.Invoke(object) }() return nil }) @@ -1775,3 +1982,313 @@ func docIndexJson(_ js.Value, funcArgs []js.Value) interface{} { promiseConstructor := js.Global().Get("Promise") return promiseConstructor.New(handler) } + +func encryptSubscription(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + + if len(funcArgs) != 3 { + reject.Invoke("not enough arguments. \"encryptSubscription(sessionId, podName, subscriberNameHash)\"") + return nil + } + sessionId := funcArgs[0].String() + podName := funcArgs[1].String() + subscriberNameHashStr := funcArgs[2].String() + + nameHash, err := utils.Decode(subscriberNameHashStr) + if err != nil { + reject.Invoke(fmt.Sprintf("approveSubscription failed : %s", err.Error())) + return nil + } + + var nh [32]byte + copy(nh[:], nameHash) + go func() { + ref, err := api.EncryptSubscription(sessionId, podName, nh) + if err != nil { + reject.Invoke(fmt.Sprintf("encryptSubscription failed : %s", err.Error())) + return + } + object := js.Global().Get("Object").New() + object.Set("reference", ref) + + resolve.Invoke(object) + }() + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + +func getSubscriptions(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + + if len(funcArgs) != 3 { + reject.Invoke("not enough arguments. \"getSubscriptions(sessionId)\"") + return nil + } + sessionId := funcArgs[0].String() + + go func() { + subs, err := api.GetSubscriptions(sessionId) + if err != nil { + reject.Invoke(fmt.Sprintf("getSubscriptions failed : %s", err.Error())) + return + } + object := js.Global().Get("Object").New() + subscriptions := js.Global().Get("Array").New(len(subs)) + for i, v := range subs { + subscription := js.Global().Get("Object").New() + subscription.Set("podName", v.PodName) + subscription.Set("subHash", utils.Encode(v.SubHash[:])) + subscription.Set("podAddress", v.PodAddress) + subscription.Set("validTill", v.ValidTill) + subscription.Set("infoLocation", utils.Encode(v.InfoLocation)) + subscriptions.SetIndex(i, js.ValueOf(v)) + } + object.Set("subscriptions", subscriptions) + + resolve.Invoke(object) + }() + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + +func openSubscribedPod(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + + if len(funcArgs) != 3 { + reject.Invoke("not enough arguments. \"openSubscribedPod(sessionId, subHash, keyLocation)\"") + return nil + } + sessionId := funcArgs[0].String() + subHashStr := funcArgs[1].String() + keyLocation := funcArgs[2].String() + + subHash, err := utils.Decode(subHashStr) + if err != nil { + reject.Invoke(fmt.Sprintf("openSubscribedPod failed : %s", err.Error())) + return nil + } + + var s [32]byte + copy(s[:], subHash) + + go func() { + pi, err := api.OpenSubscribedPod(sessionId, s, keyLocation) + if err != nil { + reject.Invoke(fmt.Sprintf("openSubscribedPod failed : %s", err.Error())) + return + } + + resolve.Invoke(fmt.Sprintf("%s opened successfully", pi.GetPodName())) + }() + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + +func openSubscribedPodFromReference(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + + if len(funcArgs) != 3 { + reject.Invoke("not enough arguments. \"openSubscribedPodFromReference(sessionId, reference, sellerNameHash)\"") + return nil + } + sessionId := funcArgs[0].String() + reference := funcArgs[1].String() + sellerNameHash := funcArgs[2].String() + + subHash, err := utils.Decode(sellerNameHash) + if err != nil { + reject.Invoke(fmt.Sprintf("openSubscribedPodFromReference failed : %s", err.Error())) + return nil + } + + var s [32]byte + copy(s[:], subHash) + + go func() { + pi, err := api.DecryptAndOpenSubscriptionPod(sessionId, reference, s) + if err != nil { + reject.Invoke(fmt.Sprintf("openSubscribedPodFromReference failed : %s", err.Error())) + return + } + + resolve.Invoke(fmt.Sprintf("%s opened successfully", pi.GetPodName())) + }() + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + +func getSubscribablePods(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + + if len(funcArgs) != 1 { + reject.Invoke("not enough arguments. \"getSubscribablePods(sessionId)\"") + return nil + } + sessionId := funcArgs[0].String() + + go func() { + subs, err := api.GetSubscribablePods(sessionId) + if err != nil { + reject.Invoke(fmt.Sprintf("getSubscribablePods failed : %s", err.Error())) + return + } + object := js.Global().Get("Object").New() + subscriptions := js.Global().Get("Array").New(len(subs)) + for i, v := range subs { + subscription := js.Global().Get("Object").New() + subscription.Set("subHash", utils.Encode(v.SubHash[:])) + subscription.Set("sellerNameHash", utils.Encode(v.FdpSellerNameHash[:])) + subscription.Set("seller", v.Seller.Hex()) + subscription.Set("swarmLocation", utils.Encode(v.SwarmLocation[:])) + subscription.Set("price", v.Price.Int64()) + subscription.Set("active", v.Active) + subscription.Set("earned", v.Earned.Int64()) + subscription.Set("bid", v.Bids) + subscription.Set("sells", v.Sells) + subscription.Set("reports", v.Reports) + subscriptions.SetIndex(i, js.ValueOf(v)) + } + object.Set("subscribablePods", subscriptions) + resolve.Invoke(object) + }() + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + +func getSubRequests(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + + if len(funcArgs) != 1 { + reject.Invoke("not enough arguments. \"getSubRequests(sessionId)\"") + return nil + } + sessionId := funcArgs[0].String() + + go func() { + requests, err := api.GetSubsRequests(sessionId) + if err != nil { + reject.Invoke(fmt.Sprintf("getSubRequests failed : %s", err.Error())) + return + } + object := js.Global().Get("Object").New() + subRequests := js.Global().Get("Array").New(len(requests)) + for i, v := range requests { + request := js.Global().Get("Object").New() + request.Set("subHash", utils.Encode(v.SubHash[:])) + request.Set("buyerNameHash", utils.Encode(v.FdpBuyerNameHash[:])) + request.Set("requestHash", utils.Encode(v.RequestHash[:])) + request.Set("buyer", v.Buyer.Hex()) + subRequests.SetIndex(i, js.ValueOf(v)) + } + object.Set("requests", subRequests) + resolve.Invoke(object) + }() + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + +func getSubscribablePodInfo(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + + if len(funcArgs) != 2 { + reject.Invoke("not enough arguments. \"getSubscribablePodInfo(sessionId, subHash)\"") + return nil + } + sessionId := funcArgs[0].String() + subHashStr := funcArgs[1].String() + + subHash, err := utils.Decode(subHashStr) + if err != nil { + reject.Invoke(fmt.Sprintf("getSubscribablePodInfo failed : %s", err.Error())) + return nil + } + + var s [32]byte + copy(s[:], subHash) + + go func() { + info, err := api.GetSubscribablePodInfo(sessionId, s) + if err != nil { + reject.Invoke(fmt.Sprintf("getSubscribablePodInfo failed : %s", err.Error())) + return + } + object := js.Global().Get("Object").New() + object.Set("category", info.Category) + object.Set("description", info.Description) + object.Set("fdpSellerNameHash", info.FdpSellerNameHash) + object.Set("imageUrl", info.ImageURL) + object.Set("podAddress", info.PodAddress) + object.Set("podName", info.PodName) + object.Set("price", info.Price) + object.Set("title", info.Title) + + resolve.Invoke(object) + }() + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + +func getNameHash(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + + if len(funcArgs) != 2 { + reject.Invoke("not enough arguments. \"getNameHash(sessionId, username)\"") + return nil + } + sessionId := funcArgs[0].String() + username := funcArgs[1].String() + + go func() { + nameHash, err := api.GetNameHash(sessionId, username) + if err != nil { + reject.Invoke(fmt.Sprintf("getNameHash failed : %s", err.Error())) + return + } + object := js.Global().Get("Object").New() + object.Set("namehash", utils.Encode(nameHash[:])) + + resolve.Invoke(object) + }() + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +}