diff --git a/.github/workflows/coverge.yml b/.github/workflows/coverge.yml index f5780cda..7295b7f5 100644 --- a/.github/workflows/coverge.yml +++ b/.github/workflows/coverge.yml @@ -15,7 +15,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v4 with: - go-version: '1.21.4' + go-version: '1.22.0' - name: Checkout uses: actions/checkout@v3 with: diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 15baaa60..648f7484 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -14,7 +14,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - go: ['1.21.4'] + go: ['1.22.0'] os: [ubuntu-latest, macos-latest, windows-latest] steps: - name: Setup Go @@ -41,6 +41,13 @@ jobs: - name: Lint if: matrix.os == 'ubuntu-latest' run: make lint + - name: Set up port range and TIME_WAIT + if: matrix.os == 'windows-latest' + run: | + Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters' -Name 'TcpTimedWaitDelay' -Type DWord -Value 3 -Force + Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters' -Name 'MaxUserPort' -Type DWord -Value 65534 -Force + Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters' -Name 'MaxFreeTcbs' -Type DWord -Value 65536 -Force + shell: pwsh - name: Vet if: matrix.os == 'ubuntu-latest' run: make vet diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 615666a6..66fd6340 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -18,7 +18,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v4 with: - go-version: '1.21.4' + go-version: '1.22.0' - name: Checkout uses: actions/checkout@v3 with: @@ -45,7 +45,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v4 with: - go-version: '1.21.4' + go-version: '1.22.0' - name: Checkout uses: actions/checkout@v3 with: @@ -88,7 +88,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v4 with: - go-version: '1.21.4' + go-version: '1.22.0' - name: Checkout uses: actions/checkout@v3 with: diff --git a/.gitignore b/.gitignore index fdaf6278..3c7567d3 100644 --- a/.gitignore +++ b/.gitignore @@ -36,5 +36,5 @@ cover.out fairos.aar fairos-sources.jar -fairos.wasm +fairos.wasm* fairos.wasm.gz \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml index 544bf7e0..ca1ae0af 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,7 +1,12 @@ run: timeout: 10m + concurrency: 4 + tests: false + linters: enable: - misspell - gofmt - unconvert +issues: + exclude-dirs: ["wasm"] \ No newline at end of file diff --git a/Makefile b/Makefile index 51e30170..6b7a9803 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ GO ?= go GOLANGCI_LINT ?= $$($(GO) env GOPATH)/bin/golangci-lint -GOLANGCI_LINT_VERSION ?= v1.55.2 +GOLANGCI_LINT_VERSION ?= v1.61.0 GOGOPROTOBUF ?= protoc-gen-gogofaster GOGOPROTOBUF_VERSION ?= v1.3.1 @@ -24,7 +24,7 @@ dist: .PHONY: lint lint: linter - $(GOLANGCI_LINT) run --skip-dirs wasm + $(GOLANGCI_LINT) run .PHONY: linter linter: @@ -33,7 +33,7 @@ linter: .PHONY: swagger swagger: which swag || ( echo "install swag for your system from https://github.com/swaggo/swag" && exit 1) - swag init -g ./cmd/server.go -d cmd/dfs,pkg/api,cmd/common,pkg/dir,pkg/file,pkg/pod,pkg/user,pkg/collection -o ./swagger + swag init -g ./cmd/server.go -d cmd/dfs,pkg/api,cmd/common,pkg/dir,pkg/file,pkg/pod,pkg/user,pkg/collection,pkg/act,pkg/utils -o ./swagger .PHONY: vet vet: diff --git a/README.md b/README.md index ced12eef..e1d1bb5f 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,20 @@ The user can share files in his pod with any other user just like in other centr Pod creation is cheap. A user can create multiple pods and use it to organise his data. for ex: Personal-Pod, Applications-Pod etc. +## (NEW) Access Control Trie (ACT) Integration +### Overview +We have introduced a new feature that integrates Swarm's Access Control Trie (ACT) into fairOS-dfs to enable user-based access control. This enhancement allows for more granular permissions and secure data sharing among users. + +### What is ACT? +The Access Control Trie (ACT) is a mechanism provided by Swarm for managing access permissions to resources stored on the Swarm network. It allows publishers to grant or revoke access to specific grantees. + +### How is ACT Integrated into fairOS-dfs? +In the native Swarm implementation, ACT is node-based and lacks the concept of users, which is not suitable for user-centric applications like fairOS-dfs. We have integrated ACT in such a way that: + +- User-Based Initialization: Access control is initialized with a user's key, tying permissions directly to user identities. +- Grantee Management: Users can be added as grantees by their public keys, allowing specific users to access shared resources. +- Secure Sharing: Instead of sharing the pod sharing reference directly, we wrap that reference using ACT and share the wrapped actRef. This ensures that only authorized users can access the shared content, even if the actRef is obtained by others. + ## (NEW) What is a group? A group is a shared drive created by a user. It is basically a pod, but on steroids. Group Owner can add members and update permissions. Members with "write" permission can create and store any number of files or directories in a group. @@ -200,4 +214,91 @@ network: "testnet" bee: bee-api-endpoint: http://localhost:1633 # bee running on mainnet postage-batch-id: -``` \ No newline at end of file +``` + +### Integrating git with dfs + +To integrate git with dfs, we need to set the `git` configuration in the config file. We only need to set the credential helper for local git repositories. + +We create a file `.dfs-credentials` with the following content at any given location +``` +#!/bin/bash +token_file="" # this needs to be absolute path + +username="" +password="" + +dfs="" # http://localhost:9090 for local running fairOS-dfs server + +# Function to get the access token using the username and password +get_access_token() { + local response=$(curl -s -X POST "$dfs/v2/user/login" -H "Content-Type: application/json" -d "{\"userName\": \"$username\", \"password\": \"$password\"}") + access_token=$(echo "$response" | jq -r '.accessToken') + # check if response has access token + if [ "$access_token" == "null" ]; then + exit 1 + fi + echo "$access_token" > "$token_file" + echo "$access_token" +} + +get_saved_access_token() { + if [[ -f "$token_file" ]]; then + local saved_token=$(sed -n '1p' "$token_file") + if [ "$saved_token" == "null" ] || [ "$saved_token" == "" ]; then + return 1 + fi + local response=$(curl --write-out '%{http_code}' --silent --output /dev/null -s -X POST "$dfs/v1/user/stat" -H "Content-Type: application/json" -H "Authorisation: Bearer $saved_token" ) + # check if response had success http code + if [[ response -eq 200 ]]; then + echo "$saved_token" + return 0 + else + rm "$token_file" + return 1 + fi + fi + return 1 +} + +access_token=$(get_saved_access_token) +if [[ $? -ne 0 ]]; then + access_token=$(get_access_token) +fi +echo "username=$username" +echo "password=$access_token" + +exit 0 +``` + +After creating this file, we need to set the `credential.helper` in the git configuration + +``` +git config --local credential.helper "" +``` + +#### How to push to dfs + +Currently, we only support pushing once, so its sort of archive. We can push the git repository to dfs using the following command + +``` +git init # initialize the git repository, run this inside the directory that you want to push to dfs +git add . # add all the files to the git repository +git commit -m "Initial commit" # commit the changes +git remote add origin /v1/git//.git # add the remote origin +git config --local credential.helper "" # set the credential helper +git push -u origin master # push the changes to the remote origin +``` + +### How to clone from dfs + +``` +git config --local credential.helper "" +git clone /v1/git//.git +``` + +NOTE: Before pushing into a pod, we have to first create a pod if it does not exist. A pod can not be used as two different repos. +Dfs stores the files of the repo as a git pack file. So, we cannot access each file of the repo individually. although we can access other files from dfs api as expected. + + + diff --git a/cmd/common/request.go b/cmd/common/request.go index 1d70f451..7c7c764f 100644 --- a/cmd/common/request.go +++ b/cmd/common/request.go @@ -29,6 +29,12 @@ type UserLoginRequest struct { Password string `json:"password,omitempty"` } +// UserSignatureLoginRequest is the request body for user login with signature +type UserSignatureLoginRequest struct { + Signature string `json:"signature,omitempty"` + Password string `json:"password,omitempty"` +} + // PodRequest is the request body for pod creation type PodRequest struct { PodName string `json:"podName,omitempty"` diff --git a/cmd/dfs-cli/cmd/act.go b/cmd/dfs-cli/cmd/act.go new file mode 100644 index 00000000..120dd0f1 --- /dev/null +++ b/cmd/dfs-cli/cmd/act.go @@ -0,0 +1,126 @@ +package cmd + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "net/http" + "strings" + + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" + + "github.com/fairdatasociety/fairOS-dfs/pkg/api" +) + +func actNew(actName, publicKey string) { + url := fmt.Sprintf("%s/%s?grantee=%s", actGrantee, actName, publicKey) + data, err := fdfsAPI.postReq(http.MethodPost, url, nil) + if err != nil { + fmt.Println("could not create act: ", err) + return + } + message := strings.ReplaceAll(string(data), "\n", "") + fmt.Println(message) +} + +func actGrantRevoke(actName, key, action string) { + url := fmt.Sprintf("%s/%s", actGrantee, actName) + switch action { + case "grant": + url = fmt.Sprintf("%s?grant=%s", url, key) + case "revoke": + url = fmt.Sprintf("%s?revoke=%s", url, key) + default: + fmt.Println("invalid action") + } + data, err := fdfsAPI.postReq(http.MethodPatch, url, nil) + if err != nil { + fmt.Println("could not create act: ", err) + return + } + message := strings.ReplaceAll(string(data), "\n", "") + fmt.Println(message) +} + +func actListGrantees(actName string) { + url := fmt.Sprintf("%s/%s", actGrantee, actName) + data, err := fdfsAPI.postReq(http.MethodGet, url, nil) + if err != nil { + fmt.Println("could not create act: ", err) + return + } + message := strings.ReplaceAll(string(data), "\n", "") + fmt.Println(message) +} + +func actPodShare(actName, podName string) { + url := fmt.Sprintf("%s/%s/%s", actSharePod, actName, podName) + data, err := fdfsAPI.postReq(http.MethodPost, url, nil) + if err != nil { + fmt.Println("could not create act: ", err) + return + } + message := strings.ReplaceAll(string(data), "\n", "") + fmt.Println(message) +} + +func actListAll() { + data, err := fdfsAPI.postReq(http.MethodGet, actList, nil) + if err != nil { + fmt.Println("could not create act: ", err) + return + } + message := strings.ReplaceAll(string(data), "\n", "") + fmt.Println(message) +} + +func actPodsShared(actName string) { + url := fmt.Sprintf("%s/%s", actSharedPods, actName) + data, err := fdfsAPI.postReq(http.MethodGet, url, nil) + if err != nil { + fmt.Println("could not create act: ", err) + return + } + message := strings.ReplaceAll(string(data), "\n", "") + fmt.Println(message) +} + +func actSaveSharedPod(actName, reference, topic, owner, ownerPublicKey string) { + url := fmt.Sprintf("%s/%s", actSavePod, actName) + topicBytes, err := base64.StdEncoding.DecodeString(topic) + if err != nil { + fmt.Println("could not save act: ", err) + return + } + content := &api.Content{ + Reference: reference, + Topic: topicBytes, + Owner: owner, + OwnerPublicKey: ownerPublicKey, + } + data, err := json.Marshal(content) + if err != nil { + fmt.Println("could not save act: ", err) + return + } + resp, err := fdfsAPI.postReq(http.MethodPost, url, data) + if err != nil { + fmt.Println("could not create act: ", err) + return + } + message := strings.ReplaceAll(string(resp), "\n", "") + fmt.Println(message) +} + +func actOpenSharedPod(actName string) { + url := fmt.Sprintf("%s/%s", actOpenPod, actName) + data, err := fdfsAPI.postReq(http.MethodPost, url, nil) + if err != nil { + fmt.Println("could not open act: ", err) + return + } + currentPod = actName + currentDirectory = utils.PathSeparator + message := strings.ReplaceAll(string(data), "\n", "") + fmt.Println(message) +} diff --git a/cmd/dfs-cli/cmd/fdfs-api.go b/cmd/dfs-cli/cmd/fdfs-api.go index 8f48d963..1ee16aa2 100644 --- a/cmd/dfs-cli/cmd/fdfs-api.go +++ b/cmd/dfs-cli/cmd/fdfs-api.go @@ -107,7 +107,7 @@ func (s *fdfsClient) getAccessToken() string { func (s *fdfsClient) postReq(method, urlPath string, jsonBytes []byte) ([]byte, error) { // prepare the request - fullUrl := fmt.Sprintf(s.url + urlPath) + fullUrl := fmt.Sprintf("%s%s", s.url, urlPath) var req *http.Request var err error if jsonBytes != nil { @@ -125,7 +125,6 @@ func (s *fdfsClient) postReq(method, urlPath string, jsonBytes []byte) ([]byte, return nil, err } } - if s.getAccessToken() != "" { req.Header.Add("Authorization", "Bearer "+s.getAccessToken()) } @@ -178,7 +177,7 @@ func (s *fdfsClient) postReq(method, urlPath string, jsonBytes []byte) ([]byte, } func (s *fdfsClient) getReq(urlPath, argsString string) ([]byte, error) { - fullUrl := fmt.Sprintf(s.url + urlPath) + fullUrl := fmt.Sprintf("%s%s", s.url, urlPath) var req *http.Request var err error if argsString != "" { @@ -270,7 +269,7 @@ func (s *fdfsClient) uploadMultipartFile(urlPath, fileName string, fileSize int6 return nil, err } - fullUrl := fmt.Sprintf(s.url + urlPath) + fullUrl := fmt.Sprintf("%s%s", s.url, urlPath) req, err := http.NewRequest(http.MethodPost, fullUrl, body) if err != nil { return nil, err @@ -312,7 +311,7 @@ func (s *fdfsClient) uploadMultipartFile(urlPath, fileName string, fileSize int6 func (s *fdfsClient) downloadMultipartFile(method, urlPath string, arguments map[string]string, out *os.File) (int64, error) { // prepare the request - fullUrl := fmt.Sprintf(s.url + urlPath) + fullUrl := fmt.Sprintf("%s%s", s.url, urlPath) var req *http.Request var err error diff --git a/cmd/dfs-cli/cmd/filesystem.go b/cmd/dfs-cli/cmd/filesystem.go index 28f5816f..5fa12bfc 100644 --- a/cmd/dfs-cli/cmd/filesystem.go +++ b/cmd/dfs-cli/cmd/filesystem.go @@ -236,10 +236,7 @@ func downloadFile(podName, localFileName, podFileName string) { fmt.Println("download failed: ", err) return } - if err = out.Close(); err != nil { - fmt.Println("download failed: ", err) - return - } + defer out.Close() args := make(map[string]string) args["podName"] = podName diff --git a/cmd/dfs-cli/cmd/prompt.go b/cmd/dfs-cli/cmd/prompt.go index c06d0caa..7c4da7b0 100644 --- a/cmd/dfs-cli/cmd/prompt.go +++ b/cmd/dfs-cli/cmd/prompt.go @@ -96,10 +96,17 @@ const ( apiDocLoadJson = apiVersion + "/doc/loadjson" apiDocIndexJson = apiVersion + "/doc/indexjson" - apiUserSignupV2 = apiVersionV2 + "/user/signup" - apiUserLoginV2 = apiVersionV2 + "/user/login" - apiUserPresentV2 = apiVersionV2 + "/user/present" - apiUserDeleteV2 = apiVersionV2 + "/user/delete" + apiUserSignupV2 = apiVersionV2 + "/user/signup" + apiUserLoginV2 = apiVersionV2 + "/user/login" + apiUserSignatureLogin = apiVersionV2 + "/user/login-with-signature" + apiUserPresentV2 = apiVersionV2 + "/user/present" + apiUserDeleteV2 = apiVersionV2 + "/user/delete" + actGrantee = apiVersion + "/act/grantee" + actSharePod = apiVersion + "/act/share-pod" + actList = apiVersion + "/act/list" + actSharedPods = apiVersion + "/act/act-shared-pods" + actSavePod = apiVersion + "/act/save-act-pod" + actOpenPod = apiVersion + "/act/open-act-pod" ) func newPrompt() { @@ -144,6 +151,7 @@ var userSuggestions = []prompt.Suggest{ {Text: "new", Description: "create a new user (v2)"}, {Text: "del", Description: "delete a existing user (v2)"}, {Text: "login", Description: "login to a existing user (v2)"}, + {Text: "signatureLogin", Description: "login with signature"}, {Text: "logout", Description: "logout from a logged-in user"}, {Text: "present", Description: "is user present (v2)"}, {Text: "stat", Description: "shows information about a user"}, @@ -185,6 +193,17 @@ var docSuggestions = []prompt.Suggest{ {Text: "loadjson", Description: "load the json file in to the newly created document db"}, } +var actSuggestions = []prompt.Suggest{ + {Text: "new", Description: "creates a new act"}, + {Text: "grantRevoke", Description: "grant nad revoke users in act"}, + {Text: "lsGrantees", Description: "list all grantees in act"}, + {Text: "share", Description: "share a pod in act"}, + {Text: "ls", Description: "list all acts"}, + {Text: "lsContent", Description: "list all pods shared in act"}, + {Text: "save", Description: "save shared act"}, + {Text: "open", Description: "open act pod"}, +} + var suggestions = []prompt.Suggest{ {Text: "user new", Description: "create a new user"}, {Text: "user del", Description: "delete a existing user"}, @@ -236,6 +255,14 @@ var suggestions = []prompt.Suggest{ {Text: "rmdir", Description: "remove a existing directory"}, {Text: "pwd", Description: "show the current working directory"}, {Text: "rm", Description: "remove a file"}, + {Text: "act new", Description: "creates a new act"}, + {Text: "act grantRevoke", Description: "grant nad revoke users in act"}, + {Text: "act lsGrantees", Description: "list all grantees in act"}, + {Text: "act share", Description: "share a pod in act"}, + {Text: "act ls", Description: "list all acts"}, + {Text: "act lsContent", Description: "list all pods shared in act"}, + {Text: "act save", Description: "save shared act"}, + {Text: "act open", Description: "open act pod"}, } func completer(in prompt.Document) []prompt.Suggest { @@ -252,6 +279,8 @@ func completer(in prompt.Document) []prompt.Suggest { return prompt.FilterHasPrefix(kvSuggestions, in.GetWordBeforeCursor(), true) } else if strings.HasPrefix(in.TextBeforeCursor(), "doc") { return prompt.FilterHasPrefix(docSuggestions, in.GetWordBeforeCursor(), true) + } else if strings.HasPrefix(in.TextBeforeCursor(), "act") { + return prompt.FilterHasPrefix(actSuggestions, in.GetWordBeforeCursor(), true) } return prompt.FilterHasPrefix(suggestions, w, true) } @@ -280,6 +309,7 @@ func executor(in string) { case "new": if len(blocks) < 3 { fmt.Println("invalid command. Missing \"userName\" argument") + fmt.Println("\nuser new ") return } userName := blocks[2] @@ -301,6 +331,7 @@ func executor(in string) { case "login": if len(blocks) < 3 { fmt.Println("invalid command. Missing \"userName\" argument") + fmt.Println("\nuser login ") return } userName := blocks[2] @@ -308,9 +339,22 @@ func executor(in string) { currentPod = "" currentDirectory = "" currentPrompt = getCurrentPrompt() + case "signatureLogin": + if len(blocks) < 3 { + fmt.Println("invalid command. Missing \"signature\" argument") + fmt.Println("\nuser signatureLogin ") + return + } + signature := blocks[2] + fmt.Println("signatureLogin", signature) + signatureLogin(signature, apiUserSignatureLogin) + currentPod = "" + currentDirectory = "" + currentPrompt = getCurrentPrompt() case "present": if len(blocks) < 3 { fmt.Println("invalid command. Missing \"userName\" argument") + fmt.Println("\nuser present ") return } userName := blocks[2] @@ -319,6 +363,7 @@ func executor(in string) { case "del": if currentUser == "" { fmt.Println("please login as user to do the operation") + fmt.Println("\nuser del") return } deleteUser(apiUserDeleteV2) @@ -329,6 +374,7 @@ func executor(in string) { case "logout": if currentUser == "" { fmt.Println("please login as user to do the operation") + fmt.Println("\nuser logout") return } logoutUser() @@ -339,6 +385,7 @@ func executor(in string) { case "loggedin": if len(blocks) < 3 { fmt.Println("invalid command. Missing \"userName\" argument") + fmt.Println("\nuser loggedin ") return } userName := blocks[2] @@ -347,6 +394,7 @@ func executor(in string) { case "stat": if currentUser == "" { fmt.Println("please login as user to do the operation") + fmt.Println("\nuser stat") return } statUser() @@ -368,6 +416,7 @@ func executor(in string) { case "new": if len(blocks) < 3 { fmt.Println("invalid command. Missing \"podName\" argument") + fmt.Println("\npod new ") return } podName := blocks[2] @@ -376,6 +425,7 @@ func executor(in string) { case "del": if len(blocks) < 3 { fmt.Println("invalid command. Missing \"podName\" argument") + fmt.Println("\npod del ") return } podName := blocks[2] @@ -386,6 +436,7 @@ func executor(in string) { case "open": if len(blocks) < 3 { fmt.Println("invalid command. Missing \"podName\" argument") + fmt.Println("\npod open ") return } podName := blocks[2] @@ -405,6 +456,7 @@ func executor(in string) { } if len(blocks) < 3 { fmt.Println("invalid command. Missing \"podName\" argument") + fmt.Println("\npod stat ") return } podName := blocks[2] @@ -878,6 +930,7 @@ func executor(in string) { } if len(blocks) < 4 { fmt.Println("invalid command. Missing one or more arguments") + fmt.Println("\nupload ") return } fileName := filepath.Base(blocks[1]) @@ -902,6 +955,7 @@ func executor(in string) { } if len(blocks) < 3 { fmt.Println("invalid command. Missing one or more arguments") + fmt.Println("\ndownload ") return } localDir := blocks[1] @@ -1012,6 +1066,80 @@ func executor(in string) { sharingRefString := blocks[1] fileReceiveInfo(currentPod, sharingRefString) currentPrompt = getCurrentPrompt() + case "act": + if currentUser == "" { + fmt.Println("login as a user to execute these commands") + return + } + if len(blocks) < 2 { + log.Println("invalid command.") + help() + return + } + switch blocks[1] { + case "new": + if len(blocks) < 4 { + fmt.Println("invalid command. Missing \"actName\" argument") + return + } + actName := blocks[2] + grantee := blocks[3] + actNew(actName, grantee) + + case "grantRevoke": + if len(blocks) < 5 { + fmt.Println("invalid command. Missing \"actName\", \"public-key\", \"action\" argument") + return + } + actName := blocks[2] + key := blocks[3] + action := blocks[4] + actGrantRevoke(actName, key, action) + case "lsGrantees": + if len(blocks) < 3 { + fmt.Println("invalid command. Missing \"actName\" argument") + return + } + actName := blocks[2] + actListGrantees(actName) + case "share": + if len(blocks) < 4 { + fmt.Println("invalid command. Missing \"actName\" argument") + return + } + actName := blocks[2] + podName := blocks[3] + actPodShare(actName, podName) + case "ls": + actListAll() + case "lsContent": + if len(blocks) < 3 { + fmt.Println("invalid command. Missing \"actName\" argument") + return + } + actName := blocks[2] + actPodsShared(actName) + case "save": + if len(blocks) < 7 { + fmt.Println("invalid command. Missing arguments") + fmt.Println("act (act-name) (reference) (topic) (owner-address) (owner-public-key)") + return + } + actName := blocks[2] + reference := blocks[3] + topic := blocks[4] + ownerAddress := blocks[5] + ownerPublicKey := blocks[6] + actSaveSharedPod(actName, reference, topic, ownerAddress, ownerPublicKey) + case "open": + if len(blocks) < 3 { + fmt.Println("invalid command. Missing \"actName\" argument") + return + } + actName := blocks[2] + actOpenSharedPod(actName) + currentPrompt = getCurrentPrompt() + } default: fmt.Println("invalid command") } @@ -1023,6 +1151,7 @@ func help() { fmt.Println(" - user (user-name) (mnemonic) - create a new user and login as that user") fmt.Println(" - user - deletes a logged-in user") fmt.Println(" - user (user-name) - login as a given user") + fmt.Println(" - user (signature) - login with signature") fmt.Println(" - user - logout a logged-in user") fmt.Println(" - user (user-name) - returns true if the user is present, false otherwise") fmt.Println(" - user - shows information about a user") @@ -1079,6 +1208,15 @@ func help() { fmt.Println(" - help - display this help") fmt.Println(" - exit - exits from the prompt") + fmt.Println(" - act (act-name) (grantee-public-key) - creates a new act") + fmt.Println(" - act (act-name) (public-key) (action) - grant or revoke user in act") + fmt.Println(" - act - list all grantees") + fmt.Println(" - act (act-name) (pod-name)- share a pod in act") + fmt.Println(" - act - list all acts") + fmt.Println(" - act (act-name) - list all pods shared in act") + fmt.Println(" - act (act-name) (reference) (topic) (owner-address) (owner-public-key) - save shared act") + fmt.Println(" - act (act-name) - open act pod") + } func getCurrentPrompt() string { diff --git a/cmd/dfs-cli/cmd/user.go b/cmd/dfs-cli/cmd/user.go index 3301baf8..1135ba6b 100644 --- a/cmd/dfs-cli/cmd/user.go +++ b/cmd/dfs-cli/cmd/user.go @@ -66,10 +66,18 @@ func userNew(userName, mnemonic string) { fmt.Println("Please store the 12 words mnemonic safely") fmt.Println("if you loose that, you cannot recover the data in-case of an emergency.") fmt.Println("you can also use that mnemonic to access the data in-case this device is lost") - + fmt.Println("=============== Mnemonic Start ==========================") + fmt.Println(resp.Mnemonic) + fmt.Println("=============== Mnemonic End ==========================") + fmt.Println("=============== PublicKey Start ==========================") + fmt.Println(resp.PublicKey) + fmt.Println("=============== PublicKey End ==========================") fdfsAPI.setAccessToken(resp.AccessToken) currentUser = userName + message := strings.ReplaceAll(string(data), "\n", "") + fmt.Println(message) + } func userLogin(userName, apiEndpoint string) { @@ -94,7 +102,9 @@ func userLogin(userName, apiEndpoint string) { fmt.Println("create user: ", err) return } - + fmt.Println("=============== PublicKey Start ==========================") + fmt.Println(resp.PublicKey) + fmt.Println("=============== PublicKey End ==========================") currentUser = userName message := strings.ReplaceAll(string(data), "\n", "") fdfsAPI.setAccessToken(resp.AccessToken) @@ -102,6 +112,36 @@ func userLogin(userName, apiEndpoint string) { fmt.Println(message) } +func signatureLogin(signature, apiEndpoint string) { + password := getPassword() + loginUser := common.UserSignatureLoginRequest{ + Signature: signature, + Password: password, + } + jsonData, err := json.Marshal(loginUser) + if err != nil { + fmt.Println("login user: error marshalling request") + return + } + data, err := fdfsAPI.postReq(http.MethodPost, apiEndpoint, jsonData) + if err != nil { + fmt.Println("login user: ", err) + return + } + var resp api.UserSignupResponse + err = json.Unmarshal(data, &resp) + if err != nil { + fmt.Println("create user: ", err) + return + } + + currentUser = resp.Address + message := strings.ReplaceAll(string(data), "\n", "") + fdfsAPI.setAccessToken(resp.AccessToken) + + fmt.Println(message) +} + func deleteUser(apiEndpoint string) { password := getPassword() delUser := common.UserSignupRequest{ diff --git a/cmd/dfs/cmd/config.go b/cmd/dfs/cmd/config.go index 9f8c85f1..4ce46149 100644 --- a/cmd/dfs/cmd/config.go +++ b/cmd/dfs/cmd/config.go @@ -12,6 +12,7 @@ var ( optionVerbosity = "verbosity" optionBeeApi = "bee.bee-api-endpoint" optionBeePostageBatchId = "bee.postage-batch-id" + optionBeeRedundancyLevel = "bee.redundancy-level" optionFeedCacheSize = "feed.cache-size" optionFeedCacheTTL = "feed.cache-ttl" optionCookieDomain = "cookie-domain" diff --git a/cmd/dfs/cmd/dev.go b/cmd/dfs/cmd/dev.go index c9221a8b..842f36ce 100644 --- a/cmd/dfs/cmd/dev.go +++ b/cmd/dfs/cmd/dev.go @@ -2,17 +2,19 @@ package cmd import ( "context" + "crypto/rand" + "encoding/hex" "fmt" "os" "os/signal" "syscall" "testing" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/api" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/dfs" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/ensm/eth/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -53,7 +55,7 @@ func startDevServer() { }) fmt.Println("Bee running at: ", beeUrl) logger := logging.New(os.Stdout, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy("0"), bee.WithPinning(true)) ens := mock2.NewMockNamespaceManager() users := user.NewUsers(mockClient, ens, -1, 0, logger) @@ -72,6 +74,8 @@ func startDevServer() { }() done := make(chan os.Signal, 1) signal.Notify(done, syscall.SIGINT, syscall.SIGTERM) - + batchOk := make([]byte, 32) + _, _ = rand.Read(batchOk) + fmt.Println(hex.EncodeToString(batchOk)) <-done } diff --git a/cmd/dfs/cmd/root.go b/cmd/dfs/cmd/root.go index e7bfe5d3..75b6f334 100644 --- a/cmd/dfs/cmd/root.go +++ b/cmd/dfs/cmd/root.go @@ -162,6 +162,7 @@ func writeConfig() { c.Set(optionVerbosity, defaultVerbosity) c.Set(optionBeeApi, defaultBeeApi) c.Set(optionBeePostageBatchId, "") + c.Set(optionBeeRedundancyLevel, 0) c.Set(optionCookieDomain, defaultCookieDomain) if err := c.WriteConfigAs(cfgFile); err != nil { diff --git a/cmd/dfs/cmd/server.go b/cmd/dfs/cmd/server.go index 7d32ee07..e0653240 100644 --- a/cmd/dfs/cmd/server.go +++ b/cmd/dfs/cmd/server.go @@ -44,14 +44,15 @@ import ( ) var ( - pprof bool - swag bool - httpPort string - pprofPort string - cookieDomain string - postageBlockId string - corsOrigins []string - handler *api.Handler + pprof bool + swag bool + httpPort string + pprofPort string + cookieDomain string + postageBlockId string + redundancyLevel uint8 + corsOrigins []string + handler *api.Handler //go:embed .well-known staticFiles embed.FS @@ -101,6 +102,9 @@ can consume it.`, if err := config.BindPFlag(optionRPC, cmd.Flags().Lookup("rpc")); err != nil { return err } + if err := config.BindPFlag(optionBeeRedundancyLevel, cmd.Flags().Lookup("redundancyLevel")); err != nil { + fmt.Println("setting redundancy level to 0") + } return config.BindPFlag(optionBeePostageBatchId, cmd.Flags().Lookup("postageBlockId")) }, RunE: func(cmd *cobra.Command, args []string) error { @@ -113,9 +117,15 @@ can consume it.`, pprofPort = config.GetString(optionDFSPprofPort) cookieDomain = config.GetString(optionCookieDomain) postageBlockId = config.GetString(optionBeePostageBatchId) + redundancyLevel = uint8(config.GetUint(optionBeeRedundancyLevel)) corsOrigins = config.GetStringSlice(optionCORSAllowedOrigins) verbosity = config.GetString(optionVerbosity) + if redundancyLevel > 4 { + fmt.Println("\nredundancyLevel should be between 0 and 4") + return fmt.Errorf("redundancyLevel should be between 0 and 4") + } + if postageBlockId == "" { _ = cmd.Help() fmt.Println("\npostageBlockId is required to run server") @@ -184,8 +194,7 @@ can consume it.`, logger.Info("verbosity : ", verbosity) logger.Info("httpPort : ", httpPort) logger.Info("pprofPort : ", pprofPort) - logger.Info("pprofPort : ", pprofPort) - logger.Info("pprofPort : ", pprofPort) + logger.Info("redundancyLevel: ", redundancyLevel) logger.Info("cookieDomain : ", cookieDomain) logger.Info("feedCacheSize : ", config.GetInt(optionFeedCacheSize)) logger.Info("feedCacheTTL : ", config.GetString(optionFeedCacheTTL)) @@ -203,6 +212,7 @@ can consume it.`, Logger: logger, FeedCacheSize: config.GetInt(optionFeedCacheSize), FeedCacheTTL: config.GetString(optionFeedCacheTTL), + RedundancyLevel: redundancyLevel, } hdlr, err := api.New(ctx, opts) @@ -246,6 +256,7 @@ func init() { serverCmd.Flags().String("feedCacheTTL", "0s", "How long to keep feed updates in lru cache. 0s to disable") serverCmd.Flags().String("cookieDomain", defaultCookieDomain, "the domain to use in the cookie") serverCmd.Flags().String("postageBlockId", "", "the postage block used to store the data in bee") + serverCmd.Flags().Uint8("redundancyLevel", 0, "redundancy level for swarm erasure coding") serverCmd.Flags().StringSlice("cors-origins", defaultCORSAllowedOrigins, "allow CORS headers for the given origins") serverCmd.Flags().String("ens-network", "testnet", "network to use for authentication [not related to swarm network] (mainnet/testnet/play)") serverCmd.Flags().String("rpc", "", "rpc endpoint for ens network. xDai for mainnet | Sepolia for testnet | local fdp-play rpc endpoint for play") @@ -286,6 +297,7 @@ func startHttpService(logger logging.Logger) *http.Server { router.HandleFunc("/public-file", handler.PublicPodGetFileHandler) router.HandleFunc("/public-dir", handler.PublicPodGetDirHandler) router.HandleFunc("/public-kv", handler.PublicPodKVEntryGetHandler) + router.HandleFunc("/public-pod-snapshot", handler.PodReceiveSnapshotHandler).Methods("GET") redirectHandler := func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, r.URL.Path+"/", http.StatusMovedPermanently) @@ -322,6 +334,7 @@ func startHttpService(logger logging.Logger) *http.Server { baseRouterV2.Use(handler.LogMiddleware) baseRouterV2.HandleFunc("/user/signup", handler.UserSignupV2Handler).Methods("POST") baseRouterV2.HandleFunc("/user/login", handler.UserLoginV2Handler).Methods("POST") + baseRouterV2.HandleFunc("/user/login-with-signature", handler.UserLoginWithSignature).Methods("POST") baseRouterV2.HandleFunc("/user/present", handler.UserPresentV2Handler).Methods("GET") userRouterV2 := baseRouterV2.PathPrefix("/user/").Subrouter() userRouterV2.Use(handler.LoginMiddleware) @@ -436,6 +449,28 @@ func startHttpService(logger logging.Logger) *http.Server { docRouter.HandleFunc("/entry/get", handler.DocEntryGetHandler).Methods("GET") docRouter.HandleFunc("/entry/del", handler.DocEntryDelHandler).Methods("DELETE") + gitRouter := baseRouter.PathPrefix("/git/").Subrouter() + gitRouter.Use(handler.GitAuthMiddleware) + gitRouter.HandleFunc("/{user}/{repo}.git/HEAD", handler.GitInfoRef).Methods("GET") + gitRouter.HandleFunc("/{user}/{repo}.git/info/refs", handler.GitInfoRef).Methods("GET") + gitRouter.HandleFunc("/{user}/{repo}.git/git-upload-pack", handler.GitUploadPack).Methods("POST") + gitRouter.HandleFunc("/{user}/{repo}.git/git-receive-pack", handler.GitReceivePack).Methods("POST") + + actRouter := baseRouter.PathPrefix("/act/").Subrouter() + actRouter.Use(handler.LoginMiddleware) + + // list acts + // owner + actRouter.HandleFunc("/grantee/{actName}", handler.CreateGranteeHandler).Methods("POST") + actRouter.HandleFunc("/grantee/{actName}", handler.GrantRevokeHandler).Methods("PATCH") + actRouter.HandleFunc("/grantee/{actName}", handler.ListGranteesHandler).Methods("GET") + actRouter.HandleFunc("/share-pod/{actName}/{podName}", handler.ACTPodShareHandler).Methods("POST") + actRouter.HandleFunc("/list", handler.ACTListHandler).Methods("GET") + actRouter.HandleFunc("/act-shared-pods/{actName}", handler.ACTSharedPods).Methods("GET") + // grantee + actRouter.HandleFunc("/save-act-pod/{actName}", handler.ACTSavePod).Methods("POST") + actRouter.HandleFunc("/open-act-pod/{actName}", handler.ACTOpenPod).Methods("POST") + var origins []string for _, c := range corsOrigins { c = strings.TrimSpace(c) diff --git a/cmd/dfs/cmd/server_test.go b/cmd/dfs/cmd/server_test.go index 00547bf4..82cadbbc 100644 --- a/cmd/dfs/cmd/server_test.go +++ b/cmd/dfs/cmd/server_test.go @@ -17,21 +17,22 @@ import ( "testing" "time" - "github.com/fairdatasociety/fairOS-dfs/pkg/acl/acl" - "github.com/stretchr/testify/assert" - - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/cmd/common" + "github.com/fairdatasociety/fairOS-dfs/pkg/acl/acl" "github.com/fairdatasociety/fairOS-dfs/pkg/api" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/dfs" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/ensm/eth/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" + "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/fairdatasociety/fairOS-dfs/pkg/user" "github.com/gorilla/websocket" "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" ) var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz") @@ -56,11 +57,11 @@ func TestApis(t *testing.T) { Post: mockpost.New(mockpost.WithAcceptAll()), }) - logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + logger := logging.New(os.Stdout, logrus.PanicLevel) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) ens := mock2.NewMockNamespaceManager() - users := user.NewUsers(mockClient, ens, 500, 0, logger) + users := user.NewUsers(mockClient, ens, -1, 0, logger) dfsApi := dfs.NewMockDfsAPI(mockClient, users, logger) handler = api.NewMockHandler(dfsApi, logger, []string{"http://localhost:3000"}) defer handler.Close() @@ -1084,6 +1085,309 @@ func TestApis(t *testing.T) { } }) + t.Run("signup-login-pod-dir-file-snapshot", func(t *testing.T) { + c := http.Client{Timeout: time.Duration(1) * time.Minute} + userRequest := &common.UserSignupRequest{ + UserName: randStringRunes(16), + Password: randStringRunes(12), + } + + userTwoRequest := &common.UserSignupRequest{ + UserName: randStringRunes(16), + Password: randStringRunes(12), + } + + userBytes, err := json.Marshal(userRequest) + if err != nil { + t.Fatal(err) + } + + userTwoBytes, err := json.Marshal(userTwoRequest) + if err != nil { + t.Fatal(err) + } + + cookies := [][]string{} + + for _, user := range [][]byte{userBytes, userTwoBytes} { + signupRequestDataHttpReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", basev2, string(common.UserSignup)), bytes.NewBuffer(user)) + if err != nil { + t.Fatal(err) + } + signupRequestDataHttpReq.Header.Add("Content-Type", "application/json") + signupRequestDataHttpReq.Header.Add("Content-Length", strconv.Itoa(len(user))) + signupRequestResp, err := c.Do(signupRequestDataHttpReq) + if err != nil { + t.Fatal(err) + } + + err = signupRequestResp.Body.Close() + if err != nil { + t.Fatal(err) + } + if signupRequestResp.StatusCode != http.StatusCreated { + t.Fatal("Signup failed", signupRequestResp.StatusCode) + } + + userLoginHttpReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", basev2, string(common.UserLogin)), bytes.NewBuffer(user)) + if err != nil { + t.Fatal(err) + + } + userLoginHttpReq.Header.Add("Content-Type", "application/json") + userLoginHttpReq.Header.Add("Content-Length", strconv.Itoa(len(user))) + userLoginResp, err := c.Do(userLoginHttpReq) + if err != nil { + t.Fatal(err) + } + err = userLoginResp.Body.Close() + if err != nil { + t.Fatal(err) + } + if userLoginResp.StatusCode != http.StatusOK { + t.Fatal("user should be able to login") + } + cookie := userLoginResp.Header["Set-Cookie"] + cookies = append(cookies, cookie) + } + + // pod new + podRequest := &common.PodRequest{ + PodName: randStringRunes(16), + } + podBytes, err := json.Marshal(podRequest) + if err != nil { + t.Fatal(err) + } + podNewHttpReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", basev1, string(common.PodNew)), bytes.NewBuffer(podBytes)) + if err != nil { + t.Fatal(err) + } + podNewHttpReq.Header.Set("Cookie", cookies[0][0]) + podNewHttpReq.Header.Add("Content-Type", "application/json") + podNewHttpReq.Header.Add("Content-Length", strconv.Itoa(len(podBytes))) + podNewResp, err := c.Do(podNewHttpReq) + if err != nil { + t.Fatal(err) + } + + err = podNewResp.Body.Close() + if err != nil { + t.Fatal(err) + } + if podNewResp.StatusCode != 201 { + t.Fatal("pod creation failed") + } + + entries := []struct { + path string + isDir bool + size int64 + content []byte + }{ + { + path: "/dir1", + isDir: true, + }, + { + path: "/dir2", + isDir: true, + }, + { + path: "/dir3", + isDir: true, + }, + { + path: "/file1", + size: 1024 * 1024, + }, + { + path: "/dir1/file11", + size: 1024 * 512, + }, + { + path: "/dir1/file12", + size: 1024 * 1024, + }, + { + path: "/dir3/file31", + size: 1024 * 1024, + }, + { + path: "/dir3/file32", + size: 1024 * 1024, + }, + { + path: "/dir3/file33", + size: 1024, + }, + { + path: "/dir2/dir4", + isDir: true, + }, + { + path: "/dir2/dir4/dir5", + isDir: true, + }, + { + path: "/dir2/dir4/file241", + size: 5 * 1024 * 1024, + }, + { + path: "/dir2/dir4/dir5/file2451", + size: 10 * 1024 * 1024, + }, + } + + for _, v := range entries { + if v.isDir { + mkdirRqst := common.FileSystemRequest{ + PodName: podRequest.PodName, + DirectoryPath: v.path, + } + mkDirBytes, err := json.Marshal(mkdirRqst) + if err != nil { + t.Fatal(err) + } + mkDirHttpReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", basev1, string(common.DirMkdir)), bytes.NewBuffer(mkDirBytes)) + if err != nil { + t.Fatal(err) + + } + mkDirHttpReq.Header.Set("Cookie", cookies[0][0]) + mkDirHttpReq.Header.Add("Content-Type", "application/json") + mkDirHttpReq.Header.Add("Content-Length", strconv.Itoa(len(mkDirBytes))) + mkDirResp, err := c.Do(mkDirHttpReq) + if err != nil { + t.Fatal(err) + } + err = mkDirResp.Body.Close() + if err != nil { + t.Fatal(err) + } + if mkDirResp.StatusCode != 201 { + t.Fatal("mkdir failed") + } + } else { + body := new(bytes.Buffer) + writer := multipart.NewWriter(body) + contentLength := fmt.Sprintf("%d", v.size) + + err = writer.WriteField("podName", podRequest.PodName) + if err != nil { + t.Fatal(err) + } + err = writer.WriteField("contentLength", contentLength) + if err != nil { + t.Fatal(err) + } + err = writer.WriteField("dirPath", filepath.Dir(v.path)) + if err != nil { + t.Fatal(err) + } + err = writer.WriteField("blockSize", "1Mb") + if err != nil { + t.Fatal(err) + } + part, err := writer.CreateFormFile("files", filepath.Base(v.path)) + if err != nil { + t.Fatal(err) + } + reader := &io.LimitedReader{R: rand.Reader, N: v.size} + _, err = io.Copy(part, reader) + if err != nil { + t.Fatal(err) + } + + err = writer.Close() + if err != nil { + t.Fatal(err) + } + + uploadReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", basev1, string(common.FileUpload)), body) + if err != nil { + t.Fatal(err) + + } + uploadReq.Header.Set("Cookie", cookies[0][0]) + contentType := fmt.Sprintf("multipart/form-data;boundary=%v", writer.Boundary()) + uploadReq.Header.Add("Content-Type", contentType) + uploadResp, err := c.Do(uploadReq) + if err != nil { + t.Fatal(err) + } + err = uploadResp.Body.Close() + if err != nil { + t.Fatal(err) + } + if uploadResp.StatusCode != 200 { + t.Fatal("upload failed") + } + } + } + <-time.After(time.Second * 2) + podShareRequest := &common.PodShareRequest{ + PodName: podRequest.PodName, + SharedPodName: "sharedPod", + } + podShareBytes, err := json.Marshal(podShareRequest) + if err != nil { + t.Fatal(err) + } + podShareHttpReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", basev1, "/pod/share"), bytes.NewBuffer(podShareBytes)) + if err != nil { + t.Fatal(err) + } + podShareHttpReq.Header.Set("Cookie", cookies[0][0]) + podShareHttpReq.Header.Add("Content-Type", "application/json") + podShareHttpReq.Header.Add("Content-Length", strconv.Itoa(len(podShareBytes))) + podShareResp, err := c.Do(podShareHttpReq) + if err != nil { + t.Fatal(err) + } + + podShareData := &api.PodSharingReference{} + podShareRespBytes, err := io.ReadAll(podShareResp.Body) + if err != nil { + t.Fatal(err) + } + + err = json.Unmarshal(podShareRespBytes, podShareData) + if err != nil { + t.Fatal(err) + } + err = podShareResp.Body.Close() + if err != nil { + t.Fatal(err) + } + if podShareResp.StatusCode != 200 { + t.Fatal("pod share failed") + } + podSnapHttpReq, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s%s%s", "http://localhost:9090", "/public-pod-snapshot?sharingRef=", podShareData.Reference), http.NoBody) + if err != nil { + t.Fatal(err) + } + podSnapHttpReq.Header.Add("Content-Type", "application/json") + podSnapResp, err := c.Do(podSnapHttpReq) + if err != nil { + t.Fatal(err) + } + + data, err := io.ReadAll(podSnapResp.Body) + if err != nil { + t.Fatal(err) + } + snap := &pod.DirSnapShot{} + err = json.Unmarshal(data, snap) + if err != nil { + t.Fatal(err) + } + err = podSnapResp.Body.Close() + if err != nil { + t.Fatal(err) + } + }) + t.Run("group-test", func(t *testing.T) { c := http.Client{Timeout: time.Duration(1) * time.Minute} userRequest := &common.UserSignupRequest{ @@ -1345,6 +1649,258 @@ func TestApis(t *testing.T) { } }) + t.Run("act-publisher", func(t *testing.T) { + c := http.Client{Timeout: time.Duration(1) * time.Minute} + userRequest := &common.UserSignupRequest{ + UserName: randStringRunes(16), + Password: randStringRunes(12), + } + + userTwoRequest := &common.UserSignupRequest{ + UserName: randStringRunes(16), + Password: randStringRunes(12), + } + + userBytes, err := json.Marshal(userRequest) + if err != nil { + t.Fatal(err) + } + + userTwoBytes, err := json.Marshal(userTwoRequest) + if err != nil { + t.Fatal(err) + } + userResps := []*api.UserSignupResponse{} + cookies := [][]string{} + + for _, user := range [][]byte{userBytes, userTwoBytes} { + signupRequestDataHttpReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", basev2, string(common.UserSignup)), bytes.NewBuffer(user)) + if err != nil { + t.Fatal(err) + } + signupRequestDataHttpReq.Header.Add("Content-Type", "application/json") + signupRequestDataHttpReq.Header.Add("Content-Length", strconv.Itoa(len(user))) + signupRequestResp, err := c.Do(signupRequestDataHttpReq) + if err != nil { + t.Fatal(err) + } + + err = signupRequestResp.Body.Close() + if err != nil { + t.Fatal(err) + } + if signupRequestResp.StatusCode != http.StatusCreated { + t.Fatal("Signup failed", signupRequestResp.StatusCode) + } + + userLoginHttpReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", basev2, string(common.UserLogin)), bytes.NewBuffer(user)) + if err != nil { + t.Fatal(err) + + } + userLoginHttpReq.Header.Add("Content-Type", "application/json") + userLoginHttpReq.Header.Add("Content-Length", strconv.Itoa(len(user))) + userLoginResp, err := c.Do(userLoginHttpReq) + if err != nil { + t.Fatal(err) + } + var resp api.UserSignupResponse + data, err := io.ReadAll(userLoginResp.Body) + if err != nil { + t.Fatal(err) + } + err = json.Unmarshal(data, &resp) + if err != nil { + t.Fatal(err) + } + userResps = append(userResps, &resp) + err = userLoginResp.Body.Close() + if err != nil { + t.Fatal(err) + } + if userLoginResp.StatusCode != http.StatusOK { + t.Fatal("user should be able to login") + } + cookie := userLoginResp.Header["Set-Cookie"] + cookies = append(cookies, cookie) + } + + // pod new + podRequest := &common.PodRequest{ + PodName: randStringRunes(16), + } + podBytes, err := json.Marshal(podRequest) + if err != nil { + t.Fatal(err) + } + podNewHttpReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", basev1, string(common.PodNew)), bytes.NewBuffer(podBytes)) + if err != nil { + t.Fatal(err) + } + podNewHttpReq.Header.Set("Cookie", cookies[0][0]) + podNewHttpReq.Header.Add("Content-Type", "application/json") + podNewHttpReq.Header.Add("Content-Length", strconv.Itoa(len(podBytes))) + podNewResp, err := c.Do(podNewHttpReq) + if err != nil { + t.Fatal(err) + } + + err = podNewResp.Body.Close() + if err != nil { + t.Fatal(err) + } + if podNewResp.StatusCode != 201 { + t.Fatal("pod creation failed") + } + + entries := []struct { + path string + isDir bool + size int64 + content []byte + }{ + { + path: "/file1", + size: 1024 * 1024, + }, + } + + for _, v := range entries { + + body := new(bytes.Buffer) + writer := multipart.NewWriter(body) + contentLength := fmt.Sprintf("%d", v.size) + + err = writer.WriteField("podName", podRequest.PodName) + if err != nil { + t.Fatal(err) + } + err = writer.WriteField("contentLength", contentLength) + if err != nil { + t.Fatal(err) + } + err = writer.WriteField("dirPath", filepath.Dir(v.path)) + if err != nil { + t.Fatal(err) + } + err = writer.WriteField("blockSize", "1Mb") + if err != nil { + t.Fatal(err) + } + part, err := writer.CreateFormFile("files", filepath.Base(v.path)) + if err != nil { + t.Fatal(err) + } + reader := &io.LimitedReader{R: rand.Reader, N: v.size} + _, err = io.Copy(part, reader) + if err != nil { + t.Fatal(err) + } + + err = writer.Close() + if err != nil { + t.Fatal(err) + } + + uploadReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", basev1, string(common.FileUpload)), body) + if err != nil { + t.Fatal(err) + + } + uploadReq.Header.Set("Cookie", cookies[0][0]) + contentType := fmt.Sprintf("multipart/form-data;boundary=%v", writer.Boundary()) + uploadReq.Header.Add("Content-Type", contentType) + uploadResp, err := c.Do(uploadReq) + if err != nil { + t.Fatal(err) + } + err = uploadResp.Body.Close() + if err != nil { + t.Fatal(err) + } + if uploadResp.StatusCode != 200 { + t.Fatal("upload failed") + } + } + <-time.After(time.Second * 2) + url := fmt.Sprintf("%s%s/%s?grantee=%s", basev1, "/act/grantee", "actone", userResps[1].PublicKey) + actCreateHttpReq, err := http.NewRequest(http.MethodPost, url, http.NoBody) + if err != nil { + t.Fatal(err) + } + actCreateHttpReq.Header.Set("Cookie", cookies[0][0]) + actCreateResp, err := c.Do(actCreateHttpReq) + if err != nil { + t.Fatal(err) + } + + _, err = io.ReadAll(actCreateResp.Body) + if err != nil { + t.Fatal(err) + } + + url = fmt.Sprintf("%s%s/%s/%s", basev1, "/act/share-pod", "actone", podRequest.PodName) + actSharePodHttpReq, err := http.NewRequest(http.MethodPost, url, http.NoBody) + if err != nil { + t.Fatal(err) + } + actSharePodHttpReq.Header.Set("Cookie", cookies[0][0]) + actSharePodResp, err := c.Do(actSharePodHttpReq) + if err != nil { + t.Fatal(err) + } + + actSharePodRespBytes, err := io.ReadAll(actSharePodResp.Body) + if err != nil { + t.Fatal(err) + } + content := &api.Content{} + + err = json.Unmarshal(actSharePodRespBytes, content) + if err != nil { + t.Fatal(err) + } + fmt.Println(content) + + url = fmt.Sprintf("%s%s/%s", basev1, "/act/save-act-pod", "actone") + actSavePodHttpReq, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(actSharePodRespBytes)) + if err != nil { + t.Fatal(err) + } + actSavePodHttpReq.Header.Set("Cookie", cookies[1][0]) + actSavePodHttpReq.Header.Add("Content-Type", "application/json") + actSavePodHttpReq.Header.Add("Content-Length", strconv.Itoa(len(actSharePodRespBytes))) + + actSavePodResp, err := c.Do(actSavePodHttpReq) + if err != nil { + t.Fatal(err) + } + + actSavePodRespBytes, err := io.ReadAll(actSavePodResp.Body) + if err != nil { + t.Fatal(err) + } + fmt.Println(string(actSavePodRespBytes)) + + url = fmt.Sprintf("%s%s/%s", basev1, "/act/open-act-pod", "actone") + actOpenPodHttpReq, err := http.NewRequest(http.MethodPost, url, http.NoBody) + if err != nil { + t.Fatal(err) + } + actOpenPodHttpReq.Header.Set("Cookie", cookies[1][0]) + + actOpenPodResp, err := c.Do(actOpenPodHttpReq) + if err != nil { + t.Fatal(err) + } + + actOpenPodRespBytes, err := io.ReadAll(actOpenPodResp.Body) + if err != nil { + t.Fatal(err) + } + fmt.Println(string(actOpenPodRespBytes)) + }) + t.Run("ws test", func(t *testing.T) { u := url.URL{Scheme: "ws", Host: base, Path: "/ws/v1/"} header := http.Header{} diff --git a/go.mod b/go.mod index 2c8b4f65..42ddc994 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,17 @@ module github.com/fairdatasociety/fairOS-dfs -go 1.21 +go 1.22.0 require ( - github.com/btcsuite/btcd v0.22.3 + github.com/asabya/swarm-act v0.0.0-20241022090815-9b494c0051de + github.com/asabya/swarm-blockstore v0.0.0-20241022084926-8d6753f32697 + github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/c-bata/go-prompt v0.2.6 github.com/dustin/go-humanize v1.0.1 - github.com/ethereum/go-ethereum v1.13.12 - github.com/ethersphere/bee v1.18.2 + github.com/ethereum/go-ethereum v1.14.7 + github.com/ethersphere/bee/v2 v2.2.0 github.com/ethersphere/bmt v0.1.4 - github.com/fairdatasociety/fairOS-dfs-utils v0.0.0-20221230123929-aec4ed8b854d - github.com/golang-jwt/jwt/v5 v5.2.0 + github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/gorilla/mux v1.8.1 @@ -21,45 +22,44 @@ require ( github.com/miguelmota/go-ethereum-hdwallet v0.1.2 github.com/mitchellh/go-homedir v1.1.0 github.com/plexsysio/taskmanager v0.0.0-20211220123746-de5ebdd49ae2 - github.com/rs/cors v1.10.1 + github.com/rs/cors v1.11.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.18.2 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/swaggo/http-swagger v1.3.4 github.com/swaggo/swag v1.16.3 github.com/tinygrasshopper/bettercsv v0.0.1 github.com/tyler-smith/go-bip39 v1.1.0 github.com/wealdtech/go-ens/v3 v3.6.0 go.uber.org/goleak v1.3.0 - golang.org/x/crypto v0.19.0 - golang.org/x/term v0.17.0 + golang.org/x/crypto v0.25.0 + golang.org/x/term v0.22.0 gopkg.in/yaml.v2 v2.4.0 resenje.org/jsonhttp v0.2.3 ) require ( - github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect github.com/KyleBanks/depth v1.2.1 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.10.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/bits-and-blooms/bitset v1.13.0 // indirect + github.com/btcsuite/btcd v0.22.3 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect - github.com/casbin/casbin/v2 v2.35.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect - github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect + github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/ethersphere/go-price-oracle-abi v0.1.0 // indirect - github.com/ethersphere/go-storage-incentives-abi v0.6.0 // indirect - github.com/ethersphere/go-sw3-abi v0.4.0 // indirect + github.com/ethereum/c-kzg-4844 v1.0.0 // indirect + github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect + github.com/ethersphere/go-price-oracle-abi v0.2.0 // indirect + github.com/ethersphere/go-storage-incentives-abi v0.9.1 // indirect + github.com/ethersphere/go-sw3-abi v0.6.5 // indirect github.com/ethersphere/langos v1.0.0 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -72,52 +72,54 @@ require ( github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator/v10 v10.11.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/google/uuid v1.4.0 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/holiman/uint256 v1.2.4 // indirect + github.com/holiman/uint256 v1.3.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/klauspost/compress v1.17.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect + github.com/klauspost/compress v1.17.6 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/klauspost/reedsolomon v1.11.8 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/libp2p/go-libp2p v0.30.0 // indirect + github.com/libp2p/go-libp2p v0.33.2 // 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 - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/mattn/go-tty v0.0.3 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.55 // indirect + github.com/miekg/dns v1.1.58 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multiaddr v0.11.0 // indirect + github.com/multiformats/go-multiaddr v0.12.3 // indirect github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multicodec v0.9.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect - github.com/multiformats/go-multistream v0.4.1 // indirect + github.com/multiformats/go-multistream v0.5.0 // indirect github.com/multiformats/go-varint v0.0.7 // indirect + github.com/onsi/ginkgo v1.16.4 // indirect + github.com/onsi/gomega v1.27.10 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pkg/term v1.2.0-beta.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/client_golang v1.18.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.47.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect @@ -127,7 +129,7 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/supranational/blst v0.3.11 // indirect + github.com/supranational/blst v0.3.13 // indirect github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect @@ -137,17 +139,17 @@ require ( github.com/vmihailenco/msgpack/v5 v5.3.4 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/wealdtech/go-multicodec v1.4.0 // indirect - github.com/yusufpapurcu/wmi v1.2.2 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.15.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.2.1 // indirect diff --git a/go.sum b/go.sum index 73bf230b..5560e5bf 100644 --- a/go.sum +++ b/go.sum @@ -2,26 +2,28 @@ github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/HdrHistogram/hdrhistogram-go v0.0.0-20200919145931-8dac23c8dac1 h1:nEjGZtKHMK92888VT6XkzKwyiW14v5FFRGeWq2uV7N0= github.com/HdrHistogram/hdrhistogram-go v0.0.0-20200919145931-8dac23c8dac1/go.mod h1:nxrse8/Tzg2tg3DZcZjm6qEclQKK70g0KxO61gFFZD4= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= -github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/asabya/swarm-act v0.0.0-20241022090815-9b494c0051de h1:d5PDY+pU7QCIu3VNSftUq6rc4hNC6GfxH8vI1JItWNU= +github.com/asabya/swarm-act v0.0.0-20241022090815-9b494c0051de/go.mod h1:JKFHSirdVKLWOdJpk7cl8732JiI+a9G64dzB58CEO8w= +github.com/asabya/swarm-blockstore v0.0.0-20241022084926-8d6753f32697 h1:MhH/TMo8jvCafB/WcI8MKajuWuodymKHiLZLGAQ35nE= +github.com/asabya/swarm-blockstore v0.0.0-20241022084926-8d6753f32697/go.mod h1:Tc8wjIjbbV0Ofrr3JPmxDcbmg571M6yFEdKOqWelWgo= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= -github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= +github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.3 h1:kYNaWFvOw6xvqP0vR20RP1Zq1DVMBxEO8QN5d1/EfNg= github.com/btcsuite/btcd v0.22.3/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= -github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= -github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= @@ -35,22 +37,20 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/c-bata/go-prompt v0.2.6 h1:POP+nrHE+DfLYx370bedwNhsqmpCUynWPxuHi0C5vZI= github.com/c-bata/go-prompt v0.2.6/go.mod h1:/LMAke8wD2FsNu9EXNdHxNLbd9MedkPnCdfpU9wwHfY= -github.com/casbin/casbin/v2 v2.35.0 h1:f0prVg9LgTJTihjAxWEZhfJptXvah1GpZh12sb5KXNA= -github.com/casbin/casbin/v2 v2.35.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= -github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.0.8 h1:8QG/764wK+vmEYoOlfobpe12EQcS81ukx/a4hdVMxNw= -github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM= -github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.1 h1:XnKU22oiCLy2Xn8vp1re67cXg4SAasg/WDt1NtcRFaw= +github.com/cockroachdb/pebble v1.1.1/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= @@ -59,42 +59,42 @@ github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJ github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= -github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= -github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= -github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI= +github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -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/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= -github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.13.12 h1:iDr9UM2JWkngBHGovRJEQn4Kor7mT4gt9rUZqB5M29Y= -github.com/ethereum/go-ethereum v1.13.12/go.mod h1:hKL2Qcj1OvStXNSEDbucexqnEt1Wh4Cz329XsjAalZY= -github.com/ethersphere/bee v1.18.2 h1:bSngtJGDBYkB8HcPHMjKcoBiYNllqChuykpy1IVaGfA= -github.com/ethersphere/bee v1.18.2/go.mod h1:k5jZVd/o6WCz9JLACiJKccyR0efhftZ98Qbx5GYMb+k= +github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= +github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.14.7 h1:EHpv3dE8evQmpVEQ/Ne2ahB06n2mQptdwqaMNhAT29g= +github.com/ethereum/go-ethereum v1.14.7/go.mod h1:Mq0biU2jbdmKSZoqOj29017ygFrMnB5/Rifwp980W4o= +github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A= +github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/ethersphere/bee/v2 v2.2.0 h1:UOrnGuacIlRD9RHSux9W13eI0ppsJvz6Xa0MTn6UuJ4= +github.com/ethersphere/bee/v2 v2.2.0/go.mod h1:9mrRirUnAJwSmnB9kJBx6Bo94LCgFrj2jYDJA20SIe0= github.com/ethersphere/bmt v0.1.4 h1:+rkWYNtMgDx6bkNqGdWu+U9DgGI1rRZplpSW3YhBr1Q= github.com/ethersphere/bmt v0.1.4/go.mod h1:Yd8ft1U69WDuHevZc/rwPxUv1rzPSMpMnS6xbU53aY8= -github.com/ethersphere/go-price-oracle-abi v0.1.0 h1:yg/hK8nETNvk+GEBASlbakMFv/CVp7HXiycrHw1pRV8= -github.com/ethersphere/go-price-oracle-abi v0.1.0/go.mod h1:sI/Qj4/zJ23/b1enzwMMv0/hLTpPNVNacEwCWjo6yBk= -github.com/ethersphere/go-storage-incentives-abi v0.6.0 h1:lfGViU/wJg/CyXlntNvTQpqQ2A4QYGLJ7jo+Pw+H+a4= -github.com/ethersphere/go-storage-incentives-abi v0.6.0/go.mod h1:SXvJVtM4sEsaSKD0jc1ClpDLw8ErPoROZDme4Wrc/Nc= -github.com/ethersphere/go-sw3-abi v0.4.0 h1:T3ANY+ktWrPAwe2U0tZi+DILpkHzto5ym/XwV/Bbz8g= -github.com/ethersphere/go-sw3-abi v0.4.0/go.mod h1:BmpsvJ8idQZdYEtWnvxA8POYQ8Rl/NhyCdF0zLMOOJU= +github.com/ethersphere/go-price-oracle-abi v0.2.0 h1:wtIcYLgNZHY4BjYwJCnu93SvJdVAZVvBaKinspyyHvQ= +github.com/ethersphere/go-price-oracle-abi v0.2.0/go.mod h1:sI/Qj4/zJ23/b1enzwMMv0/hLTpPNVNacEwCWjo6yBk= +github.com/ethersphere/go-storage-incentives-abi v0.9.1 h1:/FGh5Bn78hlxMu0YjSFf1APzmmrCmmThDOZMWY+G2Cs= +github.com/ethersphere/go-storage-incentives-abi v0.9.1/go.mod h1:SXvJVtM4sEsaSKD0jc1ClpDLw8ErPoROZDme4Wrc/Nc= +github.com/ethersphere/go-sw3-abi v0.6.5 h1:M5dcIe1zQYvGpY2K07UNkNU9Obc4U+A1fz68Ho/Q+XE= +github.com/ethersphere/go-sw3-abi v0.6.5/go.mod h1:BmpsvJ8idQZdYEtWnvxA8POYQ8Rl/NhyCdF0zLMOOJU= github.com/ethersphere/langos v1.0.0 h1:NBtNKzXTTRSue95uOlzPN4py7Aofs0xWPzyj4AI1Vcc= github.com/ethersphere/langos v1.0.0/go.mod h1:dlcN2j4O8sQ+BlCaxeBu43bgr4RQ+inJ+pHwLeZg5Tw= -github.com/fairdatasociety/fairOS-dfs-utils v0.0.0-20221230123929-aec4ed8b854d h1:4QgyFcv+J02YdPZ92oiCjjQ8QtGl/UbLTAypKb+WfZc= -github.com/fairdatasociety/fairOS-dfs-utils v0.0.0-20221230123929-aec4ed8b854d/go.mod h1:f4lfxKoK1n4S+2II4lyVmuvWISAMThqH+uc/XL62tzU= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= @@ -108,8 +108,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= -github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= @@ -132,17 +132,15 @@ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/j github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= -github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -150,18 +148,14 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= @@ -187,12 +181,12 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= 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/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= 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.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= -github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs= +github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= @@ -209,12 +203,14 @@ github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlT github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= +github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/reedsolomon v1.11.8 h1:s8RpUW5TK4hjr+djiOpbZJB4ksx+TdYbRH7vHQpwPOY= +github.com/klauspost/reedsolomon v1.11.8/go.mod h1:4bXRN+cVzMdml6ti7qLouuYi32KHJ5MGv0Qd8a47h6A= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -232,8 +228,8 @@ github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/libp2p/go-libp2p v0.30.0 h1:9EZwFtJPFBcs/yJTnP90TpN1hgrT/EsFfM+OZuwV87U= -github.com/libp2p/go-libp2p v0.30.0/go.mod h1:nr2g5V7lfftwgiJ78/HrID+pwvayLyqKCEirT2Y3Byg= +github.com/libp2p/go-libp2p v0.33.2 h1:vCdwnFxoGOXMKmaGHlDSnL4bM3fQeW8pgIa9DECnb40= +github.com/libp2p/go-libp2p v0.33.2/go.mod h1:zTeppLuCvUIkT118pFVzA8xzP/p2dJYOMApCkFh0Yww= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -249,19 +245,17 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= -github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= +github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= github.com/miguelmota/go-ethereum-hdwallet v0.1.2 h1:mz9LO6V7QCRkLYb0AH17t5R8KeqCe3E+hx9YXpmZeXA= github.com/miguelmota/go-ethereum-hdwallet v0.1.2/go.mod h1:fdNwFSoBFVBPnU0xpOd6l2ueqsPSH/Gch5kIvSvTGk8= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= @@ -285,8 +279,8 @@ github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYg 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-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.11.0 h1:XqGyJ8ufbCE0HmTDwx2kPdsrQ36AGPZNZX6s6xfJH10= -github.com/multiformats/go-multiaddr v0.11.0/go.mod h1:gWUm0QLR4thQ6+ZF6SXUw8YjtwQSPapICM+NmCkxHSM= +github.com/multiformats/go-multiaddr v0.12.3 h1:hVBXvPRcKG0w80VinQ23P5t7czWgg65BmIvQKjDydU8= +github.com/multiformats/go-multiaddr v0.12.3/go.mod h1:sBXrNzucqkFJhvKOiwwLyqamGa/P5EIXNPLovyhQCII= github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= @@ -296,8 +290,8 @@ github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI1 github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= -github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo= -github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q= +github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE= +github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA= github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 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= @@ -311,12 +305,13 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= @@ -331,22 +326,22 @@ github.com/plexsysio/taskmanager v0.0.0-20211220123746-de5ebdd49ae2/go.mod h1:mr github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k= +github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= +github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -378,16 +373,18 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= -github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/supranational/blst v0.3.13 h1:AYeSxdOMacwu7FBmpfloBz5pbFXDmJL33RuwnKtmTjk= +github.com/supranational/blst v0.3.13/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= 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.4 h1:q7t/XLx0n15H1Q9/tk3Y9L4n210XzJF5WtnDX64a5ww= @@ -424,8 +421,8 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRT github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= -github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= gitlab.com/nolash/go-mockbytes v0.0.7 h1:9XVFpEfY67kGBVJve3uV19kzqORdlo7V+q09OE6Yo54= gitlab.com/nolash/go-mockbytes v0.0.7/go.mod h1:KKOpNTT39j2Eo+P6uUTOncntfeKY6AFh/2CxuD5MpgE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -443,16 +440,15 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -462,16 +458,15 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -490,6 +485,7 @@ golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -501,43 +497,39 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= -golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -547,8 +539,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/pkg/account/account.go b/pkg/account/account.go index f307a940..6e2e9841 100644 --- a/pkg/account/account.go +++ b/pkg/account/account.go @@ -24,9 +24,9 @@ import ( "fmt" "strconv" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/ethereum/go-ethereum/accounts" - "github.com/fairdatasociety/fairOS-dfs-utils/crypto" + "github.com/ethersphere/bee/v2/pkg/crypto" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" hdwallet "github.com/miguelmota/go-ethereum-hdwallet" @@ -88,6 +88,42 @@ func (a *Account) CreateUserAccount(mnemonic string) (string, []byte, error) { if err != nil { return "", nil, err } + hdw, err := hdwallet.NewFromMnemonic(mnemonic) + if err != nil { // skipcq: TCV-001 + return "", nil, err + } + + // store publicKey, private key and user + a.userAccount.privateKey, err = hdw.PrivateKey(acc) + if err != nil { // skipcq: TCV-001 + return "", nil, err + } + a.userAccount.publicKey, err = hdw.PublicKey(acc) + if err != nil { // skipcq: TCV-001 + return "", nil, err + } + addrBytes, err := crypto.NewEthereumAddress(a.userAccount.privateKey.PublicKey) + if err != nil { // skipcq: TCV-001 + return "", nil, err + } + a.userAccount.address.SetBytes(addrBytes) + + seed, err := hdwallet.NewSeedFromMnemonic(mnemonic) + if err != nil { // skipcq: TCV-001 + return "", nil, err + } + + return mnemonic, seed, nil +} + +// GenerateUserAccountFromSignature create a new master account for a user. +func (a *Account) GenerateUserAccountFromSignature(signature, password string) (string, []byte, error) { + wal := newWallet(nil) + a.wallet = wal + acc, mnemonic, err := wal.GenerateWalletFromSignature(signature, password) + if err != nil { + return "", nil, err + } hdw, err := hdwallet.NewFromMnemonic(mnemonic) if err != nil { // skipcq: TCV-001 diff --git a/pkg/account/wallet.go b/pkg/account/wallet.go index 1bace280..2ce35b6e 100644 --- a/pkg/account/wallet.go +++ b/pkg/account/wallet.go @@ -17,10 +17,13 @@ limitations under the License. package account import ( + "crypto/sha256" + "encoding/hex" "fmt" "strings" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethersphere/bee/v2/pkg/crypto" hdwallet "github.com/miguelmota/go-ethereum-hdwallet" "github.com/tyler-smith/go-bip39" ) @@ -28,6 +31,8 @@ import ( const ( rootPath = "m/44'/60'/0'/0/0" genericPath = "m/44'/60'/0'/0/" + + MaxEntropyLength = 32 ) // Wallet is used to create root and pod accounts of user @@ -122,3 +127,63 @@ func (*Wallet) IsValidMnemonic(mnemonic string) error { } return nil } + +// GenerateWalletFromSignature is used to create an account from a given signature +func (w *Wallet) GenerateWalletFromSignature(signature, password string) (accounts.Account, string, error) { + if signature == "" { + return accounts.Account{}, "", fmt.Errorf("signature is empty") + } + signatureBytes, err := hex.DecodeString(signature) + if err != nil { + return accounts.Account{}, "", err + } + wallet, acc, mnemonic, err := signatureToWallet(signatureBytes) + if err != nil { // skipcq: TCV-001 + return accounts.Account{}, "", err + } + if password != "" { + pk, err := wallet.PrivateKey(acc) + if err != nil { // skipcq: TCV-001 + return accounts.Account{}, "", err + } + signer := crypto.NewDefaultSigner(pk) + passBytes := sha256.Sum256([]byte(password)) + signatureBytes, err = signer.Sign([]byte("0x" + hex.EncodeToString(passBytes[:]))) + if err != nil { + return accounts.Account{}, "", err + } + + wallet, acc, mnemonic, err = signatureToWallet(signatureBytes) + if err != nil { // skipcq: TCV-001 + return accounts.Account{}, "", err + } + _ = wallet + } + + seed, err := hdwallet.NewSeedFromMnemonic(mnemonic) + if err != nil { // skipcq: TCV-001 + return accounts.Account{}, "", err + } + w.seed = seed + return acc, mnemonic, nil +} + +func signatureToWallet(signatureBytes []byte) (*hdwallet.Wallet, accounts.Account, string, error) { + slicedSignature := signatureBytes[0:MaxEntropyLength] + + mnemonic, err := bip39.NewMnemonic(slicedSignature) + if err != nil { // skipcq: TCV-001 + return nil, accounts.Account{}, "", err + } + wallet, err := hdwallet.NewFromMnemonic(mnemonic) + if err != nil { // skipcq: TCV-001 + return nil, accounts.Account{}, "", err + } + + path := hdwallet.MustParseDerivationPath(rootPath) + acc, err := wallet.Derive(path, false) + if err != nil { // skipcq: TCV-001 + return nil, accounts.Account{}, "", err + } + return wallet, acc, mnemonic, nil +} diff --git a/pkg/account/wallet_test.go b/pkg/account/wallet_test.go index a1e710bf..514c5994 100644 --- a/pkg/account/wallet_test.go +++ b/pkg/account/wallet_test.go @@ -4,6 +4,8 @@ import ( "os" "testing" + "github.com/stretchr/testify/assert" + hdwallet "github.com/miguelmota/go-ethereum-hdwallet" "github.com/tyler-smith/go-bip39" @@ -38,3 +40,19 @@ func TestWallet(t *testing.T) { t.Fatal("invalid mnemonic") } } + +func TestSignatureToWallet(t *testing.T) { + signature := "b7f4346174a6ff79983bdb10348523de3a4bd2b4772b9f7217b997c6ca1f6abd3de015eab01818e459fad3c067e00969d9f02b808df027574da2f7fd50170a911c" + addrs := []string{"0x61E18Ac267f4d5af06D421DeA020818255678649", "0x13543e7BA5ff28AD8B203BB8e93b47D76ee2aE05"} + w := newWallet(nil) + acc, _, err := w.GenerateWalletFromSignature(signature, "") + if err != nil { + t.Fatal(err) + } + assert.Equal(t, addrs[0], acc.Address.String()) + acc, _, err = w.GenerateWalletFromSignature(signature, "111111111111") + if err != nil { + t.Fatal(err) + } + assert.Equal(t, addrs[1], acc.Address.String()) +} diff --git a/pkg/acl/acl/controller.go b/pkg/acl/acl/controller.go index 27dedaf3..501b0920 100644 --- a/pkg/acl/acl/controller.go +++ b/pkg/acl/acl/controller.go @@ -6,7 +6,7 @@ import ( "io" "sync" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" + blockstore "github.com/asabya/swarm-blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" f "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" diff --git a/pkg/act/act.go b/pkg/act/act.go new file mode 100644 index 00000000..8793b843 --- /dev/null +++ b/pkg/act/act.go @@ -0,0 +1,95 @@ +package act + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "errors" + "io" + "sync" + + "github.com/btcsuite/btcd/btcec/v2" + + swarm_act "github.com/asabya/swarm-act" + + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" + + blockstore "github.com/asabya/swarm-blockstore" + "github.com/ethereum/go-ethereum/crypto" + "github.com/fairdatasociety/fairOS-dfs/pkg/account" + "github.com/fairdatasociety/fairOS-dfs/pkg/feed" + f "github.com/fairdatasociety/fairOS-dfs/pkg/file" + "github.com/fairdatasociety/fairOS-dfs/pkg/logging" + "github.com/fairdatasociety/fairOS-dfs/pkg/taskmanager" +) + +var ( + ErrACTAlreadyExists = errors.New("ACT already exists") + ErrACTDoesNowExist = errors.New("ACT does not exist") +) + +type ACT struct { + fd *feed.API + acc *account.Account + client blockstore.Client + logger logging.Logger + tm taskmanager.TaskManagerGO + act *swarm_act.ACT + mu *sync.RWMutex +} + +func NewACT(client blockstore.Client, feed *feed.API, account *account.Account, m taskmanager.TaskManagerGO, logger logging.Logger) *ACT { + accountInfo := account.GetUserAccountInfo() + accPrivKey, _ := btcec.PrivKeyFromBytes(accountInfo.GetPrivateKey().D.Bytes()) + act := swarm_act.New(client, accPrivKey.ToECDSA(), "") + return &ACT{ + fd: feed, + acc: account, + client: client, + logger: logger, + tm: m, + act: act, + mu: &sync.RWMutex{}, + } +} + +func (t *ACT) storeUserACTs(actList List) error { + data, err := json.Marshal(actList) + if err != nil { + return err + } + + // store data as file and get metadata + // This is a very hacky way to store pod data, but it works for now + // We create a new file object with the user account address and upload the data + // We use the user private key to encrypt data. + f2 := f.NewFile("", t.client, t.fd, t.acc.GetAddress(account.UserAccountIndex), t.tm, t.logger) + privKeyBytes := crypto.FromECDSA(t.acc.GetUserAccountInfo().GetPrivateKey()) + return f2.Upload(bytes.NewReader(data), actFile, int64(len(data)), f.MinBlockSize, 0, "/", "gzip", hex.EncodeToString(privKeyBytes)) +} + +func (t *ACT) loadUserACTs() (List, error) { + actList := List{} + f2 := f.NewFile("", t.client, t.fd, t.acc.GetAddress(account.UserAccountIndex), t.tm, t.logger) + topicString := utils.CombinePathAndFile("", actFile) + privKeyBytes := crypto.FromECDSA(t.acc.GetUserAccountInfo().GetPrivateKey()) + r, _, err := f2.Download(topicString, hex.EncodeToString(privKeyBytes)) + if err != nil { // skipcq: TCV-001 + return actList, nil + } + data, err := io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + return nil, err + } + + if len(data) == 0 { + return actList, nil + } + + err = json.Unmarshal(data, &actList) + if err != nil { // skipcq: TCV-001 + return nil, err + } + + return actList, nil +} diff --git a/pkg/act/act_test.go b/pkg/act/act_test.go new file mode 100644 index 00000000..73122fab --- /dev/null +++ b/pkg/act/act_test.go @@ -0,0 +1,839 @@ +package act + +import ( + "context" + "crypto/ecdsa" + "crypto/rand" + "encoding/hex" + "fmt" + "io" + "os" + "testing" + "time" + + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/ethersphere/bee/v2/pkg/crypto" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/swarm" + "github.com/fairdatasociety/fairOS-dfs/pkg/account" + "github.com/fairdatasociety/fairOS-dfs/pkg/feed" + "github.com/fairdatasociety/fairOS-dfs/pkg/file" + "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/sirupsen/logrus" +) + +func TestACT(t *testing.T) { + storer := mockstorer.New() + beeUrl := mock.NewTestBeeServer(t, mock.TestServerOptions{ + Storer: storer, + PreventRedirect: true, + Post: mockpost.New(mockpost.WithAcceptAll()), + }) + + logger := logging.New(io.Discard, logrus.DebugLevel) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + + accounts := []*account.Account{} + for i := 0; i < 10; i++ { + acc := account.New(logger) + _, _, err := acc.CreateUserAccount("") + if err != nil { + t.Fatal(err) + } + accounts = append(accounts, acc) + } + + tm := taskmanager.New(1, 10, time.Second*15, logger) + defer func() { + _ = tm.Stop(context.Background()) + }() + sm := mock2.NewMockSubscriptionManager() + pods := []string{"test1", "test2"} + acts := []string{"testact1", "testact2"} + _ = sm + _ = pods + t.Run("create-first-act", func(t *testing.T) { + acc := accounts[0] + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) + + ownerACT := NewACT(mockClient, fd, acc, tm, logger) + actName := acts[0] + for i := 1; i < 10; i++ { + acc := accounts[i] + _, err := ownerACT.CreateUpdateACT(actName, acc.GetUserAccountInfo().GetPublicKey(), nil) + if err != nil { + t.Fatal(err) + } + <-time.After(1 * time.Second) + } + a, err := ownerACT.GetACT(actName) + if err != nil { + t.Fatal(err) + } + pubKeys, err := ownerACT.act.GetGrantees(context.Background(), swarm.NewAddress(a.GranteesRef)) + if err != nil { + t.Fatal(err) + } + if len(pubKeys) != 9 { + t.Fatal("pubkeys not matching") + } + }) + t.Run("create-first-then-revoke-act", func(t *testing.T) { + acc := accounts[0] + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) + + ownerACT := NewACT(mockClient, fd, acc, tm, logger) + actName := acts[1] + for i := 1; i < 2; i++ { + acc := accounts[i] + accPrivKey, _ := btcec.PrivKeyFromBytes(acc.GetUserAccountInfo().GetPrivateKey().D.Bytes()) + _, err := ownerACT.CreateUpdateACT(actName, accPrivKey.PubKey().ToECDSA(), nil) + if err != nil { + t.Fatal(err) + } + <-time.After(1 * time.Second) + + } + a, err := ownerACT.GetACT(actName) + if err != nil { + t.Fatal(err) + } + pubKeys, err := ownerACT.act.GetGrantees(context.Background(), swarm.NewAddress(a.GranteesRef)) + if err != nil { + t.Fatal(err) + } + if len(pubKeys) != 1 { + t.Fatal("pubkeys not matching") + } + + for i := 1; i < 2; i++ { + acc := accounts[i] + _, err := ownerACT.CreateUpdateACT(actName, nil, acc.GetUserAccountInfo().GetPublicKey()) + if err != nil { + t.Fatal(err) + } + <-time.After(1 * time.Second) + } + a, err = ownerACT.GetACT(actName) + if err != nil { + t.Fatal(err) + } + + pubKeys, err = ownerACT.act.GetGrantees(context.Background(), swarm.NewAddress(a.GranteesRef)) + if err != nil { + t.Fatal(err) + } + if len(pubKeys) != 0 { + t.Fatal("pubkeys not matching") + } + }) + t.Run("create-second-act", func(t *testing.T) { + acc := accounts[0] + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) + + ownerACT := NewACT(mockClient, fd, acc, tm, logger) + for _, actName := range acts { + for i := 1; i < 10; i++ { + acc := accounts[i] + _, err := ownerACT.CreateUpdateACT(actName, acc.GetUserAccountInfo().GetPublicKey(), nil) + if err != nil { + t.Fatal(err) + } + <-time.After(1 * time.Second) + } + } + list, err := ownerACT.GetList() + if err != nil { + t.Fatal(err) + } + if len(list) != 2 { + t.Fatal("acts not matching") + } + }) + + t.Run("act-file-upload", func(t *testing.T) { + ownerAcc := accounts[0] + fd := feed.New(ownerAcc.GetUserAccountInfo(), mockClient, -1, 0, logger) + pod1 := pod.NewPod(mockClient, fd, ownerAcc, tm, sm, -1, 0, logger) + podPassword, _ := utils.GetRandString(pod.PasswordLength) + _, err := pod1.CreatePod(pods[0], "", podPassword) + if err != nil { + t.Fatalf("error creating pod %s: %s", pods[0], err.Error()) + } + + p, err := pod1.OpenPod(pods[0]) + if err != nil { + t.Fatalf("error opening pod %s: %s", pods[0], err.Error()) + } + + maxfiles := 1 + filePath := "/" + for i := 1; i <= maxfiles; i++ { + fileName, _ := utils.GetRandString(100) + compression := "" + fileSize := int64(1000) + blockSize := file.MinBlockSize + _, err = uploadFile(t, p.GetFile(), filePath, fileName, compression, p.GetPodPassword(), fileSize, blockSize) + if err != nil { + t.Fatal(err) + } + err = p.GetDirectory().AddEntryToDir("/", p.GetPodPassword(), fileName, true) + if err != nil { + t.Fatal(i, err) + } + } + + ref, err := pod1.PodShare(pods[0], "") + if err != nil { + t.Fatal(err) + } + reference, err := swarm.ParseHexAddress(ref) + if err != nil { + t.Fatal(err) + } + + ownerACT := NewACT(mockClient, fd, ownerAcc, tm, logger) + granteeAcc := accounts[1] + _, err = ownerACT.CreateUpdateACT(acts[0], granteeAcc.GetUserAccountInfo().GetPublicKey(), nil) + if err != nil { + t.Fatal(err) + } + <-time.After(1 * time.Second) + + respOne, err := ownerACT.GrantAccess(acts[0], reference) + if err != nil { + t.Fatal(err) + } + <-time.After(1 * time.Second) + + granteeFeed := feed.New(granteeAcc.GetUserAccountInfo(), mockClient, -1, 0, logger) + granteeACT := NewACT(mockClient, granteeFeed, granteeAcc, tm, logger) + err = granteeACT.SaveGrantedPod(acts[0], respOne) + if err != nil { + t.Fatal(err) + } + addr, err := granteeACT.GetPodAccess(acts[0]) + if err != nil { + t.Fatal(err) + } + + granteePod := pod.NewPod(mockClient, granteeFeed, granteeAcc, tm, sm, -1, 0, logger) + _, err = granteePod.ReceivePodInfo(utils.NewReference(addr.Bytes())) + if err != nil { + t.Fatal(err) + } + <-time.After(1 * time.Second) + + actAfterRevoke, err := ownerACT.CreateUpdateACT(acts[0], nil, granteeAcc.GetUserAccountInfo().GetPublicKey()) + if err != nil { + t.Fatal(err) + } + <-time.After(time.Second) + + _, err = ownerACT.act.GetGrantees(context.Background(), swarm.NewAddress(actAfterRevoke.GranteesRef)) + if err != nil { + t.Fatal(err) + } + _, err = granteeACT.GetPodAccess(acts[0]) + if err == nil { + t.Fatal("grantee should not have access") + } + }) + + t.Run("act-content-list", func(t *testing.T) { + ownerAcc := accounts[0] + fd := feed.New(ownerAcc.GetUserAccountInfo(), mockClient, -1, 0, logger) + pod1 := pod.NewPod(mockClient, fd, ownerAcc, tm, sm, -1, 0, logger) + ownerACT := NewACT(mockClient, fd, ownerAcc, tm, logger) + granteeAcc := accounts[1] + _, err := ownerACT.CreateUpdateACT(acts[1], granteeAcc.GetUserAccountInfo().GetPublicKey(), nil) + if err != nil { + t.Fatal(err) + } + <-time.After(1 * time.Second) + for i := 1; i < 10; i++ { + podPassword, _ := utils.GetRandString(pod.PasswordLength) + podname, _ := utils.GetRandString(pod.PasswordLength) + _, err := pod1.CreatePod(podname, "", podPassword) + if err != nil { + t.Fatalf("error creating pod %s: %s", podname, err.Error()) + } + ref, err := pod1.PodShare(podname, "") + if err != nil { + t.Fatal(err) + } + reference, err := swarm.ParseHexAddress(ref) + if err != nil { + t.Fatal(err) + } + _, err = ownerACT.GrantAccess(acts[1], reference) + if err != nil { + t.Fatal(err) + } + <-time.After(1 * time.Second) + } + contents, err := ownerACT.GetContentList(acts[1]) + if err != nil { + t.Fatal(err) + } + if len(contents) != 9 { + t.Fatal("contents not matching", len(contents)) + } + + }) + // + //t.Run("group-member-add", func(t *testing.T) { + // t.Skip() + // fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) + // mockAcl := acl.NewACL(mockClient, fd, logger) + // group := pod.NewGroup(mockClient, fd, acc, mockAcl, logger) + // groupName1, _ := utils.GetRandString(10) + // _, err = group.CreateGroup(groupName1) + // if err != nil { + // t.Fatalf("error creating group %s: %s", groupName1, err.Error()) + // } + // + // _, err = group.ListGroup() + // if err != nil { + // t.Fatalf("error getting groups") + // } + // + // g, err := group.OpenGroup(groupName1) + // if err != nil { + // t.Fatalf("error opening group %s: %s", groupName1, err.Error()) + // } + // maxfiles := 10 + // filePath := "/" + // for i := 1; i <= maxfiles; i++ { + // fileName, _ := utils.GetRandString(100) + // compression := "" + // fileSize := int64(1000) + // blockSize := file.MinBlockSize + // _, err = uploadFile(t, g.GetFile(), filePath, fileName, compression, g.GetPodPassword(), fileSize, blockSize) + // if err != nil { + // t.Fatal(err) + // } + // err = g.GetDirectory().AddEntryToDir("/", g.GetPodPassword(), fileName, true) + // if err != nil { + // t.Fatal(i, err) + // } + // } + // + // acc2 := account.New(logger) + // _, _, err = acc2.CreateUserAccount("") + // if err != nil { + // t.Fatal(err) + // } + // addr := acc2.GetUserAccountInfo().GetAddress() + // addrStr := addr.Hex() + // ref, err := group.AddMember(groupName1, common.HexToAddress(addrStr), acc2.GetUserAccountInfo().GetPublicKey(), acl.PermissionWrite) + // if err != nil { + // t.Fatal(err) + // } + // fd2 := feed.New(acc2.GetUserAccountInfo(), mockClient, -1, 0, logger) + // + // group2 := pod.NewGroup(mockClient, fd2, acc2, mockAcl, logger) + // err = group2.AcceptGroupInvite(ref) + // if err != nil { + // t.Fatal(err) + // } + // + // gi, err := group2.OpenGroup(groupName1) + // if err != nil { + // t.Fatal(err) + // } + // dirInode, err := gi.GetDirectory().GetInode(gi.GetPodPassword(), filePath) + // if err != nil { + // t.Fatal(err) + // } + // if len(dirInode.FileOrDirNames) != maxfiles { + // t.Fatal("files not present") + // } + //}) + // + //t.Run("group-member-check-no-permission", func(t *testing.T) { + // t.Skip() + // fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) + // mockAcl := acl.NewACL(mockClient, fd, logger) + // group := pod.NewGroup(mockClient, fd, acc, mockAcl, logger) + // groupName1, _ := utils.GetRandString(10) + // _, err = group.CreateGroup(groupName1) + // if err != nil { + // t.Fatalf("error creating group %s: %s", groupName1, err.Error()) + // } + // + // _, err = group.ListGroup() + // if err != nil { + // t.Fatalf("error getting groups") + // } + // + // _, err = group.OpenGroup(groupName1) + // if err != nil { + // t.Fatalf("error opening group %s: %s", groupName1, err.Error()) + // } + // + // acc2 := account.New(logger) + // _, _, err = acc2.CreateUserAccount("") + // if err != nil { + // t.Fatal(err) + // } + // + // fd2 := feed.New(acc2.GetUserAccountInfo(), mockClient, -1, 0, logger) + // mockAcl2 := acl.NewACL(mockClient, fd2, logger) + // + // group2 := pod.NewGroup(mockClient, fd2, acc2, mockAcl2, logger) + // groupName2, _ := utils.GetRandString(10) + // _, err = group2.CreateGroup(groupName2) + // if err != nil { + // t.Fatalf("error creating group %s: %s", groupName1, err.Error()) + // } + // + // _, err = group2.OpenGroup(groupName2) + // if err != nil { + // t.Fatal(err) + // } + // perm, err := group2.GetPermission(groupName2) + // if err != nil { + // t.Fatal(err) + // } + // if perm != acl.PermissionWrite { + // t.Fatal("permission does not match") + // } + // + // perm1, err := group.GetPermission(groupName1) + // if err != nil { + // t.Fatal(err) + // } + // if perm1 != acl.PermissionWrite { + // t.Fatal("permission does not match") + // } + //}) + // + //t.Run("group-member-check-permission", func(t *testing.T) { + // t.Skip() + // fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) + // mockAcl := acl.NewACL(mockClient, fd, logger) + // group := pod.NewGroup(mockClient, fd, acc, mockAcl, logger) + // groupName1, _ := utils.GetRandString(10) + // _, err = group.CreateGroup(groupName1) + // if err != nil { + // t.Fatalf("error creating group %s: %s", groupName1, err.Error()) + // } + // + // _, err = group.ListGroup() + // if err != nil { + // t.Fatalf("error getting groups") + // } + // + // _, err = group.OpenGroup(groupName1) + // if err != nil { + // t.Fatalf("error opening group %s: %s", groupName1, err.Error()) + // } + // + // acc2 := account.New(logger) + // _, _, err = acc2.CreateUserAccount("") + // if err != nil { + // t.Fatal(err) + // } + // addr := acc2.GetUserAccountInfo().GetAddress() + // addrStr := addr.Hex() + // ref, err := group.AddMember(groupName1, common.HexToAddress(addrStr), acc2.GetUserAccountInfo().GetPublicKey(), acl.PermissionRead) + // if err != nil { + // t.Fatal(err) + // } + // fd2 := feed.New(acc2.GetUserAccountInfo(), mockClient, -1, 0, logger) + // + // group2 := pod.NewGroup(mockClient, fd2, acc2, mockAcl, logger) + // err = group2.AcceptGroupInvite(ref) + // if err != nil { + // t.Fatal(err) + // } + // + // _, err = group2.OpenGroup(groupName1) + // if err != nil { + // t.Fatal(err) + // } + // + // perm, err := group2.GetPermission(groupName1) + // if err != nil { + // t.Fatal(err) + // } + // if perm != acl.PermissionRead { + // t.Fatal("permission not read") + // } + // + // err = group.UpdatePermission(groupName1, common.HexToAddress(addrStr), acl.PermissionWrite) + // if err != nil { + // t.Fatal(err) + // } + // perm, err = group2.GetPermission(groupName1) + // if err != nil { + // t.Fatal(err) + // } + // if perm != acl.PermissionWrite { + // t.Fatal("permission not write") + // } + //}) + // + //t.Run("group-member-upload-files", func(t *testing.T) { + // t.Skip() + // fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) + // mockAcl := acl.NewACL(mockClient, fd, logger) + // group := pod.NewGroup(mockClient, fd, acc, mockAcl, logger) + // groupName1, _ := utils.GetRandString(10) + // _, err = group.CreateGroup(groupName1) + // if err != nil { + // t.Fatalf("error creating group %s: %s", groupName1, err.Error()) + // } + // + // _, err = group.ListGroup() + // if err != nil { + // t.Fatalf("error getting groups") + // } + // + // _, err = group.OpenGroup(groupName1) + // if err != nil { + // t.Fatalf("error opening group %s: %s", groupName1, err.Error()) + // } + // + // acc2 := account.New(logger) + // _, _, err = acc2.CreateUserAccount("") + // if err != nil { + // t.Fatal(err) + // } + // addr := acc2.GetUserAccountInfo().GetAddress() + // addrStr := addr.Hex() + // ref, err := group.AddMember(groupName1, common.HexToAddress(addrStr), acc2.GetUserAccountInfo().GetPublicKey(), acl.PermissionRead) + // if err != nil { + // t.Fatal(err) + // } + // fd2 := feed.New(acc2.GetUserAccountInfo(), mockClient, -1, 0, logger) + // + // group2 := pod.NewGroup(mockClient, fd2, acc2, mockAcl, logger) + // err = group2.AcceptGroupInvite(ref) + // if err != nil { + // t.Fatal(err) + // } + // + // g, err := group2.OpenGroup(groupName1) + // if err != nil { + // t.Fatal(err) + // } + // + // fileName, _ := utils.GetRandString(100) + // compression := "" + // fileSize := int64(1000) + // blockSize := file.MinBlockSize + // _, err = uploadFile(t, g.GetFile(), "/", fileName, compression, g.GetPodPassword(), fileSize, blockSize) + // if !errors.Is(err, feed.ErrReadOnlyFeed) { + // t.Fatal(err) + // } + // + // err = group.UpdatePermission(groupName1, common.HexToAddress(addrStr), acl.PermissionWrite) + // if err != nil { + // t.Fatal(err) + // } + // + // // reopen the group to reload feed with new permission + // err = group2.CloseGroup(groupName1) + // if err != nil { + // t.Fatal(err) + // } + // g, err = group2.OpenGroup(groupName1) + // if err != nil { + // t.Fatal(err) + // } + // + // _, err = uploadFile(t, g.GetFile(), "/", fileName, compression, g.GetPodPassword(), fileSize, blockSize) + // if err != nil { + // t.Fatal(err) + // } + // err = g.GetDirectory().AddEntryToDir("/", g.GetPodPassword(), fileName, true) + // if err != nil { + // t.Fatal(err) + // } + // + // dirInode, err := g.GetDirectory().GetInode(g.GetPodPassword(), "/") + // if err != nil { + // t.Fatal(err) + // } + // if len(dirInode.FileOrDirNames) != 1 { + // t.Fatal("files not present") + // } + // if dirInode.FileOrDirNames[0] != "_F_"+fileName { + // t.Fatal("file name not correct") + // } + //}) + // + //t.Run("group-member-remove", func(t *testing.T) { + // t.Skip() + // fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) + // mockAcl := acl.NewACL(mockClient, fd, logger) + // group := pod.NewGroup(mockClient, fd, acc, mockAcl, logger) + // groupName1, _ := utils.GetRandString(10) + // _, err = group.CreateGroup(groupName1) + // if err != nil { + // t.Fatalf("error creating group %s: %s", groupName1, err.Error()) + // } + // + // _, err = group.ListGroup() + // if err != nil { + // t.Fatalf("error getting groups") + // } + // + // _, err = group.OpenGroup(groupName1) + // if err != nil { + // t.Fatalf("error opening group %s: %s", groupName1, err.Error()) + // } + // + // acc2 := account.New(logger) + // _, _, err = acc2.CreateUserAccount("") + // if err != nil { + // t.Fatal(err) + // } + // addr := acc2.GetUserAccountInfo().GetAddress() + // addrStr := addr.Hex() + // ref, err := group.AddMember(groupName1, common.HexToAddress(addrStr), acc2.GetUserAccountInfo().GetPublicKey(), acl.PermissionRead) + // if err != nil { + // t.Fatal(err) + // } + // fd2 := feed.New(acc2.GetUserAccountInfo(), mockClient, -1, 0, logger) + // + // group2 := pod.NewGroup(mockClient, fd2, acc2, mockAcl, logger) + // err = group2.AcceptGroupInvite(ref) + // if err != nil { + // t.Fatal(err) + // } + // + // err = group.RemoveMember(groupName1, common.HexToAddress(addrStr)) + // if err != nil { + // t.Fatal(err) + // } + // _, err = group2.OpenGroup(groupName1) + // if !errors.Is(err, pod.ErrPermissionDenied) { + // t.Fatal(err) + // } + //}) + // + //t.Run("group-remove", func(t *testing.T) { + // t.Skip() + // fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) + // mockAcl := acl.NewACL(mockClient, fd, logger) + // group := pod.NewGroup(mockClient, fd, acc, mockAcl, logger) + // groupName1, _ := utils.GetRandString(10) + // _, err = group.CreateGroup(groupName1) + // if err != nil { + // t.Fatalf("error creating group %s: %s", groupName1, err.Error()) + // } + // + // _, err = group.ListGroup() + // if err != nil { + // t.Fatalf("error getting groups") + // } + // + // _, err = group.OpenGroup(groupName1) + // if err != nil { + // t.Fatalf("error opening group %s: %s", groupName1, err.Error()) + // } + // + // acc2 := account.New(logger) + // _, _, err = acc2.CreateUserAccount("") + // if err != nil { + // t.Fatal(err) + // } + // addr := acc2.GetUserAccountInfo().GetAddress() + // addrStr := addr.Hex() + // ref, err := group.AddMember(groupName1, common.HexToAddress(addrStr), acc2.GetUserAccountInfo().GetPublicKey(), acl.PermissionRead) + // if err != nil { + // t.Fatal(err) + // } + // fd2 := feed.New(acc2.GetUserAccountInfo(), mockClient, -1, 0, logger) + // + // group2 := pod.NewGroup(mockClient, fd2, acc2, mockAcl, logger) + // err = group2.AcceptGroupInvite(ref) + // if err != nil { + // t.Fatal(err) + // } + // + // err = group.RemoveGroup(groupName1) + // if err != nil { + // t.Fatal(err) + // } + // _, err = group2.OpenGroup(groupName1) + // if !errors.Is(err, pod.ErrPermissionDenied) { + // t.Fatal(err) + // } + // _, err = group2.OpenGroup(groupName1) + // if !errors.Is(err, pod.ErrGroupDoesNotExist) { + // t.Fatal(err) + // } + //}) + // + //t.Run("group-add-multiple-member", func(t *testing.T) { + // t.Skip() + // fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) + // mockAcl := acl.NewACL(mockClient, fd, logger) + // group := pod.NewGroup(mockClient, fd, acc, mockAcl, logger) + // groupName1, _ := utils.GetRandString(10) + // _, err = group.CreateGroup(groupName1) + // if err != nil { + // t.Fatalf("error creating group %s: %s", groupName1, err.Error()) + // } + // + // _, err = group.ListGroup() + // if err != nil { + // t.Fatalf("error getting groups") + // } + // _, err = group.OpenGroup(groupName1) + // if err != nil { + // t.Fatalf("error opening group %s: %s", groupName1, err.Error()) + // } + // userCount := 10 + // for i := 0; i < userCount; i++ { + // acc2 := account.New(logger) + // _, _, err = acc2.CreateUserAccount("") + // if err != nil { + // t.Fatal(err) + // } + // addr := acc2.GetUserAccountInfo().GetAddress() + // addrStr := addr.Hex() + // _, err = group.AddMember(groupName1, common.HexToAddress(addrStr), acc2.GetUserAccountInfo().GetPublicKey(), acl.PermissionWrite) + // if err != nil { + // t.Fatal(err) + // } + // } + // users, err := group.GetGroupMembers(groupName1) + // if err != nil { + // t.Fatal(err) + // } + // if len(users) != userCount+1 { + // t.Fatal("users not added") + // } + //}) + +} +func uploadFile(t *testing.T, fileObject *file.File, filePath, fileName, compression, podPassword string, fileSize int64, blockSize uint32) ([]byte, error) { + // create a temp file + fd, err := os.CreateTemp("", fileName) + if err != nil { + t.Fatal(err) + } + defer os.Remove(fd.Name()) + + // write contents to file + content := make([]byte, fileSize) + _, err = rand.Read(content) + if err != nil { + t.Fatal(err) + } + if _, err = fd.Write(content); err != nil { + t.Fatal(err) + } + + // close file + uploadFileName := fd.Name() + err = fd.Close() + if err != nil { + t.Fatal(err) + } + + // open file to upload + f1, err := os.Open(uploadFileName) + if err != nil { + t.Fatal(err) + } + + // upload the temp file + 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, 0) + if err != nil { + t.Fatal(err) + } + + node := dirObject.GetDirFromDirectoryMap("/parentDir") + if pod1.GetName(node) != "parentDir" { + t.Fatal("dir name mismatch in pod") + } + if pod1.GetPath(node) != "/" { + t.Fatal("dir path mismatch in pod") + } + + // populate the directory with few directory and files + err = dirObject.MkDir("/parentDir/subDir1", podPassword, 0) + if err != nil { + t.Fatal(err) + } + err = dirObject.MkDir("/parentDir/subDir2", podPassword, 0) + if err != nil { + t.Fatal(err) + } + fileObject := info.GetFile() + _, err = uploadFile(t, fileObject, "/parentDir", "file1", "", podPassword, 100, file.MinBlockSize) + if err != nil { + t.Fatal(err) + } + err = dirObject.AddEntryToDir("/parentDir", podPassword, "file1", true) + if err != nil { + t.Fatal(err) + } + _, err = uploadFile(t, fileObject, "/parentDir", "file2", "", podPassword, 200, file.MinBlockSize) + if err != nil { + t.Fatal(err) + } + err = dirObject.AddEntryToDir("/parentDir", podPassword, "file2", true) + if err != nil { + t.Fatal(err) + } + + // close the pod + err = pod1.ClosePod(podName1) + if err != nil { + t.Fatal(err) + } + + // close the pod + err = pod1.ClosePod(podName1) + if err == nil { + t.Fatal("pod should not be open") + } +} + +func getPrivKey(keyNumber int) *ecdsa.PrivateKey { + var keyHex string + + switch keyNumber { + case 0: + keyHex = "a786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfa" + case 1: + keyHex = "b786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfb" + case 2: + keyHex = "c786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfc" + default: + panic("Invalid key number") + } + + data, err := hex.DecodeString(keyHex) + if err != nil { + panic(err) + } + + privKey, err := crypto.DecodeSecp256k1PrivateKey(data) + if err != nil { + panic(err) + } + + return privKey +} diff --git a/pkg/act/grant.go b/pkg/act/grant.go new file mode 100644 index 00000000..5310492a --- /dev/null +++ b/pkg/act/grant.go @@ -0,0 +1,206 @@ +package act + +import ( + "context" + "crypto/ecdsa" + "encoding/hex" + "fmt" + "time" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/ethersphere/bee/v2/pkg/crypto" + "github.com/ethersphere/bee/v2/pkg/swarm" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" +) + +func (t *ACT) GrantAccess(actName string, address swarm.Address) (*Content, error) { + if actName == "" { + return nil, fmt.Errorf("act name is required") + } + + t.mu.Lock() + defer t.mu.Unlock() + + list, err := t.loadUserACTs() + if err != nil { + return nil, err + } + // check if act with name already exists + act, ok := list[actName] + if !ok { + return nil, ErrACTDoesNowExist + } + owner := t.acc.GetUserAccountInfo().GetAddress() + + uploadResp, err := t.act.HandleUpload(context.Background(), address, swarm.NewAddress(act.HistoryRef)) + if err != nil { + return nil, err + } + + topic := fmt.Sprintf("%s-%s", actName, owner.String()) + topicBytes := utils.HashString(topic) + err = t.fd.UpdateFeed(owner, topicBytes, uploadResp.HistoryReference.Bytes(), nil, false) + if err != nil { + return nil, err + } + opk, err := encodeKey(t.acc.GetUserAccountInfo().GetPublicKey()) + if err != nil { + return nil, err + } + content := &Content{ + Reference: uploadResp.Reference.String(), + Topic: topicBytes, + Owner: owner, + OwnerPublicKey: opk, + AddedAt: time.Now(), + } + act.Content = append(act.Content, content) + list[actName] = act + err = t.storeUserACTs(list) + if err != nil { + return nil, err + } + return content, nil +} + +func (t *ACT) GetPodAccess(actName string) (swarm.Address, error) { + if actName == "" { + return swarm.ZeroAddress, fmt.Errorf("act name is required") + } + + t.mu.Lock() + defer t.mu.Unlock() + + list, err := t.loadUserACTs() + if err != nil { + return swarm.ZeroAddress, err + } + // check if act with name already exists + act, ok := list[actName] + if !ok { + return swarm.ZeroAddress, ErrACTDoesNowExist + } + if len(act.Content) == 0 { + return swarm.ZeroAddress, ErrACTDoesNowExist + } + + _, href, err := t.fd.GetFeedData(act.Content[0].Topic, act.Content[0].Owner, nil, false) + if err != nil { + return swarm.ZeroAddress, err + } + + ownerPubKey, err := parseKey(act.Content[0].OwnerPublicKey) + if err != nil { + return swarm.ZeroAddress, err + } + reference, err := swarm.ParseHexAddress(act.Content[0].Reference) + if err != nil { + return swarm.ZeroAddress, err + } + return t.act.HandleDownload(context.Background(), reference, swarm.NewAddress(href), ownerPubKey, time.Now().Unix()) +} + +func (t *ACT) SaveGrantedPod(actName string, c *Content) error { + if actName == "" { + return fmt.Errorf("act name is required") + } + + t.mu.Lock() + defer t.mu.Unlock() + + list, err := t.loadUserACTs() + if err != nil { + return err + } + // check if act with name already exists + _, ok := list[actName] + if ok { + return ErrACTAlreadyExists + } + reference, err := swarm.ParseHexAddress(c.Reference) + if err != nil { + return err + } + a := &Act{ + Name: actName, + CreatedAt: c.AddedAt, + HistoryRef: swarm.ZeroAddress.Bytes(), + GranteesRef: reference.Bytes(), + Content: []*Content{c}, + } + list[actName] = a + return t.storeUserACTs(list) +} + +func (t *ACT) GetGrantees(actName string) ([]string, error) { + if actName == "" { + return nil, fmt.Errorf("act name is required") + } + + t.mu.Lock() + defer t.mu.Unlock() + + list, err := t.loadUserACTs() + if err != nil { + return nil, err + } + act, ok := list[actName] + if !ok { + return nil, ErrACTDoesNowExist + } + grantees, err := t.act.GetGrantees(context.Background(), swarm.NewAddress(act.GranteesRef)) + if err != nil { + return nil, err + } + return encodeKeys(grantees) +} + +func (t *ACT) GetContentList(actName string) ([]*Content, error) { + if actName == "" { + return nil, fmt.Errorf("act name is required") + } + + t.mu.Lock() + defer t.mu.Unlock() + + list, err := t.loadUserACTs() + if err != nil { + return nil, err + } + act, ok := list[actName] + if !ok { + return nil, ErrACTDoesNowExist + } + return act.Content, nil +} + +func encodeKeys(keys []*ecdsa.PublicKey) ([]string, error) { + encodedList := make([]string, 0, len(keys)) + for _, key := range keys { + encoded, err := encodeKey(key) + if err != nil { + return nil, err + } + encodedList = append(encodedList, encoded) + } + return encodedList, nil +} + +func encodeKey(key *ecdsa.PublicKey) (string, error) { + if key == nil { + return "", fmt.Errorf("nil key found") + } + return hex.EncodeToString(crypto.EncodeSecp256k1PublicKey(key)), nil +} + +func parseKey(g string) (*ecdsa.PublicKey, error) { + h, err := hex.DecodeString(g) + if err != nil { + return nil, fmt.Errorf("failed to decode grantee: %w", err) + } + k, err := btcec.ParsePubKey(h) + if err != nil { + return nil, fmt.Errorf("failed to parse grantee public key: %w", err) + } + return k.ToECDSA(), nil +} diff --git a/pkg/act/new.go b/pkg/act/new.go new file mode 100644 index 00000000..2e615c8b --- /dev/null +++ b/pkg/act/new.go @@ -0,0 +1,157 @@ +package act + +import ( + "context" + "crypto/ecdsa" + "fmt" + "time" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/ethersphere/bee/v2/pkg/api" + "github.com/ethersphere/bee/v2/pkg/crypto" + "github.com/ethersphere/bee/v2/pkg/swarm" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" +) + +const ( + actFile = "ACTs" +) + +type List map[string]*Act + +// Act represents an Access Control Trie (ACT) with its metadata, grantees, and associated content. +type Act struct { + Name string `json:"name"` + HistoryRef []byte `json:"historyRef"` + GranteesRef []byte `json:"granteesRef"` + CreatedAt time.Time `json:"createdAt"` + Content []*Content `json:"content"` +} + +// Content represents a pod or data reference associated with the ACT. +type Content struct { + Reference string `json:"reference"` + Topic []byte `json:"topic"` + Owner utils.Address `json:"owner"` + OwnerPublicKey string `json:"ownerPublicKey"` + AddedAt time.Time `json:"addedAt"` +} + +func (t *ACT) CreateUpdateACT(actName string, publicKeyGrant, publicKeyRevoke *ecdsa.PublicKey) (*Act, error) { + if actName == "" { + return nil, fmt.Errorf("act name is required") + } + + t.mu.Lock() + defer t.mu.Unlock() + + list, err := t.loadUserACTs() + if err != nil { + return nil, err + } + if publicKeyGrant != nil { + gkBytes := crypto.EncodeSecp256k1PublicKey(publicKeyGrant) + gkParsedPublicKey, err := btcec.ParsePubKey(gkBytes) + if err != nil { + return nil, err + } + publicKeyGrant = gkParsedPublicKey.ToECDSA() + } + if publicKeyRevoke != nil { + rkBytes := crypto.EncodeSecp256k1PublicKey(publicKeyRevoke) + rkParsedPublicKey, err := btcec.ParsePubKey(rkBytes) + if err != nil { + return nil, err + } + publicKeyRevoke = rkParsedPublicKey.ToECDSA() + } + + var ( + resp = &api.GranteesPostResponse{} + grantList []*ecdsa.PublicKey + revokeList []*ecdsa.PublicKey + owner = t.acc.GetUserAccountInfo().GetAddress() + topic = fmt.Sprintf("%s-%s", actName, owner.String()) + topicBytes = utils.HashString(topic) + ) + // check if act with name already exists + act, ok := list[actName] + if !ok { + act = &Act{ + Name: actName, + CreatedAt: time.Now(), + HistoryRef: swarm.ZeroAddress.Bytes(), + GranteesRef: swarm.ZeroAddress.Bytes(), + Content: []*Content{}, + } + grantList = []*ecdsa.PublicKey{publicKeyGrant} + resp, err = t.act.CreateGrantee(context.Background(), swarm.NewAddress(act.HistoryRef), grantList) + if err != nil { + return nil, err + } + err = t.fd.CreateFeed(owner, topicBytes, resp.HistoryReference.Bytes(), nil) + if err != nil { + return nil, err + } + } else { + if publicKeyGrant == nil && publicKeyRevoke == nil { + return nil, fmt.Errorf("grant or revoke key is required") + } + if publicKeyGrant != nil { + grantList = []*ecdsa.PublicKey{publicKeyGrant} + } else { + grantList = nil + } + if publicKeyRevoke != nil { + revokeList = []*ecdsa.PublicKey{publicKeyRevoke} + } else { + revokeList = nil + } + + resp, err = t.act.RevokeGrant(context.Background(), swarm.NewAddress(act.GranteesRef), swarm.NewAddress(act.HistoryRef), grantList, revokeList) + if err != nil { + return nil, err + } + err = t.fd.UpdateFeed(owner, topicBytes, resp.HistoryReference.Bytes(), nil, false) + if err != nil { + return nil, err + } + } + + act.GranteesRef = resp.Reference.Bytes() + act.HistoryRef = resp.HistoryReference.Bytes() + + list[actName] = act + err = t.storeUserACTs(list) + if err != nil { + return nil, err + } + return act, nil +} + +func (t *ACT) GetACT(actName string) (*Act, error) { + if actName == "" { + return nil, fmt.Errorf("act name is required") + } + + t.mu.Lock() + defer t.mu.Unlock() + + list, err := t.loadUserACTs() + if err != nil { + return nil, err + } + act, ok := list[actName] + if !ok { + return nil, ErrACTDoesNowExist + } + + return act, nil +} + +func (t *ACT) GetList() (List, error) { + t.mu.Lock() + defer t.mu.Unlock() + + return t.loadUserACTs() +} diff --git a/pkg/api/act.go b/pkg/api/act.go new file mode 100644 index 00000000..77cc779c --- /dev/null +++ b/pkg/api/act.go @@ -0,0 +1,414 @@ +package api + +import ( + "crypto/ecdsa" + "encoding/hex" + "encoding/json" + "net/http" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/fairdatasociety/fairOS-dfs/pkg/act" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" + + "github.com/fairdatasociety/fairOS-dfs/pkg/auth" + "github.com/gorilla/mux" + "resenje.org/jsonhttp" +) + +type Content struct { + Reference string `json:"reference"` + Topic []byte `json:"topic"` + Owner string `json:"owner"` + OwnerPublicKey string `json:"ownerPublicKey"` +} + +// CreateGranteeHandler godoc +// +// @Summary Create ACT with grantee public key +// @Description CreateGranteeHandler is the api handler for creating act with grantee public key. +// @ID create-act +// @Tags act +// @Produce json +// @Param actName path string true "unique act identifier" +// @Param grantee query string true "grantee public key" +// @Success 201 {object} response +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /v1/act/grantee/{actName} [post] +func (h *Handler) CreateGranteeHandler(w http.ResponseWriter, r *http.Request) { + sessionId, err := auth.GetSessionIdFromRequest(r) + if err != nil { + h.logger.Errorf("sessionId parse failed: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + if sessionId == "" { + h.logger.Error("sessionId not set: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + + vars := mux.Vars(r) + actName := vars["actName"] + + userPublicKeyString := r.URL.Query().Get("grantee") + pubk, err := hex.DecodeString(userPublicKeyString) + if err != nil { + h.logger.Error("create grantee failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + pub, err := btcec.ParsePubKey(pubk) + if err != nil { + h.logger.Error("create grantee failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + err = h.dfsAPI.CreateGranteePublicKey(sessionId, actName, pub.ToECDSA()) + if err != nil { + h.logger.Error("create grantee failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + jsonhttp.Created(w, &response{Message: "act created"}) +} + +// GrantRevokeHandler godoc +// +// @Summary Grant ACT with grantee public key +// @Description GrantRevokeHandler is the api handler for granting and revoking access in an existing act. +// @ID grant-revoke-act +// @Tags act +// @Produce json +// @Param actName path string true "unique act identifier" +// @Param grant query string false "grantee public key" +// @Param revoke query string false "revoke public key" +// @Param Cookie header string true "cookie parameter" +// @Success 200 {object} response +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /v1/act/grantee/{actName} [patch] +func (h *Handler) GrantRevokeHandler(w http.ResponseWriter, r *http.Request) { + sessionId, err := auth.GetSessionIdFromRequest(r) + if err != nil { + h.logger.Errorf("sessionId parse failed: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + if sessionId == "" { + h.logger.Error("sessionId not set: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + + vars := mux.Vars(r) + actName := vars["actName"] + + grantUser := r.URL.Query().Get("grant") + revokeUser := r.URL.Query().Get("revoke") + if grantUser == "" && revokeUser == "" { + h.logger.Error("grant revoke failed: ", err) + jsonhttp.BadRequest(w, &response{Message: "grant and revoke user public key required"}) + return + } + if grantUser == revokeUser { + h.logger.Error("grant revoke failed: ", err) + jsonhttp.BadRequest(w, &response{Message: "grant and revoke user public key cannot be the same"}) + } + var ( + granteePubKey *ecdsa.PublicKey + removePubKey *ecdsa.PublicKey + ) + if grantUser != "" { + pubkg, err := hex.DecodeString(grantUser) + if err != nil { + h.logger.Error("grant revoke failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + pubg, err := btcec.ParsePubKey(pubkg) + if err != nil { + h.logger.Error("grant revoke failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + granteePubKey = pubg.ToECDSA() + } + if revokeUser != "" { + pubkr, err := hex.DecodeString(revokeUser) + if err != nil { + h.logger.Error("grant revoke failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + pubr, err := btcec.ParsePubKey(pubkr) + if err != nil { + h.logger.Error("grant revoke failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + removePubKey = pubr.ToECDSA() + } + + err = h.dfsAPI.GrantRevokeGranteePublicKey(sessionId, actName, granteePubKey, removePubKey) + if err != nil { + h.logger.Error("grant revoke failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + w.WriteHeader(http.StatusOK) +} + +// ListGranteesHandler godoc +// +// @Summary List grantees in ACT +// @Description ListGranteesHandler is the api handler for listing grantees in an existing act. +// @ID list-grantee-act +// @Tags act +// @Produce json +// @Param actName path string true "unique act identifier" +// @Param Cookie header string true "cookie parameter" +// @Success 200 {object} []string +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /v1/act/grantee/{actName} [get] +func (h *Handler) ListGranteesHandler(w http.ResponseWriter, r *http.Request) { + sessionId, err := auth.GetSessionIdFromRequest(r) + if err != nil { + h.logger.Errorf("sessionId parse failed: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + if sessionId == "" { + h.logger.Error("sessionId not set: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + + vars := mux.Vars(r) + actName := vars["actName"] + + grantees, err := h.dfsAPI.ListGrantees(sessionId, actName) + if err != nil { + h.logger.Error("list grantees failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + + jsonhttp.OK(w, grantees) +} + +// ACTPodShareHandler godoc +// +// @Summary share a pod in act +// @Description ACTPodShareHandler is the api handler for adding a pod in act. +// @ID share-pod-act +// @Tags act +// @Produce json +// @Param actName path string true "unique act identifier" +// @Param podname path string true "pod to share in act" +// @Param Cookie header string true "cookie parameter" +// @Success 200 {object} Content +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /v1/act/share-pod/{actName}/{podname} [post] +func (h *Handler) ACTPodShareHandler(w http.ResponseWriter, r *http.Request) { + sessionId, err := auth.GetSessionIdFromRequest(r) + if err != nil { + h.logger.Errorf("sessionId parse failed: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + if sessionId == "" { + h.logger.Error("sessionId not set: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + + vars := mux.Vars(r) + actName := vars["actName"] + podName := vars["podName"] + + content, err := h.dfsAPI.ACTPodShare(sessionId, podName, actName) + if err != nil { + h.logger.Error("create grantee failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + jsonhttp.OK(w, &Content{ + Reference: content.Reference, + Topic: content.Topic, + Owner: content.Owner.String(), + OwnerPublicKey: content.OwnerPublicKey, + }) +} + +// ACTListHandler godoc +// +// @Summary List acts +// @Description ACTListHandler is the api handler for listing acts. +// @ID list-act +// @Tags act +// @Produce json +// @Param Cookie header string true "cookie parameter" +// @Success 200 {object} act.List +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /v1/act/list [get] +func (h *Handler) ACTListHandler(w http.ResponseWriter, r *http.Request) { + sessionId, err := auth.GetSessionIdFromRequest(r) + if err != nil { + h.logger.Errorf("sessionId parse failed: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + if sessionId == "" { + h.logger.Error("sessionId not set: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + + list, err := h.dfsAPI.GetACTs(sessionId) + if err != nil { + h.logger.Error("list acts failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + + jsonhttp.OK(w, list) +} + +// ACTSharedPods godoc +// +// @Summary List pods in act +// @Description ACTSharedPods is the api handler for listing pods shared in act. +// @ID list-shared-pod-act +// @Tags act +// @Produce json +// @Param actName path string true "unique act identifier" +// @Param Cookie header string true "cookie parameter" +// @Success 200 {object} []act.Content +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /v1/act/act-shared-pods/{actName} [get] +func (h *Handler) ACTSharedPods(w http.ResponseWriter, r *http.Request) { + sessionId, err := auth.GetSessionIdFromRequest(r) + if err != nil { + h.logger.Errorf("sessionId parse failed: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + if sessionId == "" { + h.logger.Error("sessionId not set: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + vars := mux.Vars(r) + actName := vars["actName"] + + list, err := h.dfsAPI.GetACTContents(sessionId, actName) + if err != nil { + h.logger.Error("list contents failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + + jsonhttp.OK(w, list) +} + +// ACTOpenPod godoc +// +// @Summary Open Act pod +// @Description ACTOpenPod is the api handler for opening pod in act. +// @ID open-pod-act +// @Tags act +// @Produce json +// @Param actName path string true "unique act identifier" +// @Param Cookie header string true "cookie parameter" +// @Success 200 {object} response +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /v1/act/open-act-pod/{actName} [post] +func (h *Handler) ACTOpenPod(w http.ResponseWriter, r *http.Request) { + sessionId, err := auth.GetSessionIdFromRequest(r) + if err != nil { + h.logger.Errorf("sessionId parse failed: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + if sessionId == "" { + h.logger.Error("sessionId not set: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + vars := mux.Vars(r) + actName := vars["actName"] + + err = h.dfsAPI.OpenACTPod(sessionId, actName) + if err != nil { + h.logger.Error("open act pod failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + jsonhttp.OK(w, &response{Message: "pod opened"}) +} + +// ACTSavePod godoc +// +// @Summary Save shared acted pod in act list +// @Description ACTSavePod is the api handler for saving shared act pod. +// @ID save-pod-act +// @Tags act +// @Produce json +// @Param actName path string true "unique act identifier" +// @Param content body act.Content true "acted pod info" +// @Param Cookie header string true "cookie parameter" +// @Success 200 {object} response +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /v1/act/save-act-pod/{actName} [post] +func (h *Handler) ACTSavePod(w http.ResponseWriter, r *http.Request) { + sessionId, err := auth.GetSessionIdFromRequest(r) + if err != nil { + h.logger.Errorf("sessionId parse failed: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + if sessionId == "" { + h.logger.Error("sessionId not set: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + vars := mux.Vars(r) + actName := vars["actName"] + + contentType := r.Header.Get("Content-Type") + if contentType != jsonContentType { + h.logger.Errorf("save act pod: invalid request body type") + jsonhttp.BadRequest(w, &response{Message: "save act pod: invalid request body type"}) + return + } + + decoder := json.NewDecoder(r.Body) + var saveReq Content + err = decoder.Decode(&saveReq) + if err != nil { + h.logger.Errorf("save act pod: could not decode arguments") + jsonhttp.BadRequest(w, &response{Message: "save act pod: could not decode arguments"}) + return + } + contentReq := act.Content{ + Reference: saveReq.Reference, + Topic: saveReq.Topic, + Owner: utils.HexToAddress(saveReq.Owner), + OwnerPublicKey: saveReq.OwnerPublicKey, + } + + err = h.dfsAPI.SaveACTPod(sessionId, actName, &contentReq) + if err != nil { + h.logger.Error("save act pod failed: ", err) + jsonhttp.BadRequest(w, &response{Message: err.Error()}) + return + } + jsonhttp.OK(w, &response{Message: "pod saved"}) +} diff --git a/pkg/api/file_status.go b/pkg/api/file_status.go index 56d5c6ee..c59e776c 100644 --- a/pkg/api/file_status.go +++ b/pkg/api/file_status.go @@ -1,6 +1,7 @@ package api import ( + "errors" "net/http" "github.com/fairdatasociety/fairOS-dfs/pkg/auth" @@ -83,12 +84,12 @@ func (h *Handler) FileStatusHandler(w http.ResponseWriter, r *http.Request) { // status of file t, p, s, err := h.dfsAPI.StatusFile(driveName, podFileWithPath, sessionId, isGroup) if err != nil { - if err == dfs.ErrPodNotOpen { + if errors.Is(err, dfs.ErrPodNotOpen) { h.logger.Errorf("status: %v", err) jsonhttp.BadRequest(w, "status: "+err.Error()) return } - if err == file.ErrFileNotFound { + if errors.Is(err, file.ErrFileNotFound) { h.logger.Errorf("status: %v", err) jsonhttp.NotFound(w, "status: "+err.Error()) return diff --git a/pkg/api/git.go b/pkg/api/git.go new file mode 100644 index 00000000..bcf06afa --- /dev/null +++ b/pkg/api/git.go @@ -0,0 +1,207 @@ +package api + +import ( + "bytes" + "errors" + "fmt" + "io" + "net/http" + "strings" + + "github.com/fairdatasociety/fairOS-dfs/pkg/auth" + "github.com/fairdatasociety/fairOS-dfs/pkg/auth/jwt" + "github.com/fairdatasociety/fairOS-dfs/pkg/file" + "github.com/gorilla/mux" + "resenje.org/jsonhttp" +) + +var ( + refFile = "refFile" +) + +// GitAuthMiddleware checks the Authorization header for git auth credentials +func (h *Handler) GitAuthMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + authHeader := r.Header.Get("Authorization") + if authHeader == "" { + w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) + http.Error(w, "Authorization required", http.StatusUnauthorized) + return + } + + _, err := jwt.GetSessionIdFromGitRequest(r) + if err != nil { + http.Error(w, "Invalid username or password", http.StatusUnauthorized) + return + } + + next.ServeHTTP(w, r) + }) +} + +func (h *Handler) GitInfoRef(w http.ResponseWriter, r *http.Request) { + sessionId, err := auth.GetSessionIdFromGitRequest(r) + if err != nil { + h.logger.Errorf("sessionId parse failed: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + if sessionId == "" { + h.logger.Error("sessionId not set: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + + vars := mux.Vars(r) + pod := vars["repo"] + serviceType := r.FormValue("service") + + // check if pod exists + if _, err = h.dfsAPI.OpenPod(pod, sessionId); err != nil { + h.logger.Errorf("IsPodExist failed: ", err) + jsonhttp.BadRequest(w, &response{Message: "Repo does not exist"}) + return + } + refLine := "" + // check if ref file exists + reader, _, err := h.dfsAPI.DownloadFile(pod, fmt.Sprintf("/%s", refFile), sessionId, false) + if err == nil { + defer reader.Close() + refData, _ := io.ReadAll(reader) + if len(refData) != 0 { + refLine = fmt.Sprintf("%s\n", refData) + } + } + + w.Header().Set("Expires", "Fri, 01 Jan 2080 00:00:00 GMT") + w.Header().Set("Pragma", "no-cache") + w.Header().Set("Cache-Control", "no-cache, max-age=0, must-revalidate") + w.Header().Set("Content-Type", fmt.Sprintf("application/x-%s-advertisement", serviceType)) + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(packetWrite("# service=" + serviceType + "\n"))) + _, _ = w.Write([]byte("0000")) + if refLine != "" { + _, _ = w.Write([]byte(packetWrite(refLine))) + } else { + capabilities := "report-status object-format=sha1" + emptyList := fmt.Sprintf("0000000000000000000000000000000000000000 capabilities^{}\000%s\n", capabilities) + _, _ = w.Write([]byte(packetWrite(emptyList))) + } + _, _ = w.Write([]byte("0000")) +} + +func (h *Handler) GitUploadPack(w http.ResponseWriter, r *http.Request) { + sessionId, err := auth.GetSessionIdFromGitRequest(r) + if err != nil { + h.logger.Errorf("sessionId parse failed: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + if sessionId == "" { + h.logger.Error("sessionId not set: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + vars := mux.Vars(r) + pod := vars["repo"] + w.Header().Set("Content-Type", "application/x-git-upload-pack-result") + + reader, _, err := h.dfsAPI.DownloadFile(pod, fmt.Sprintf("/%s", refFile), sessionId, false) + if err != nil { + h.logger.Error("ref not found: ", err) + jsonhttp.BadRequest(w, &response{Message: "ref not found"}) + return + } + commitDetailsBytes, err := io.ReadAll(reader) + if err != nil { + h.logger.Error("ref not found: ", err) + jsonhttp.BadRequest(w, &response{Message: "ref not found"}) + return + } + commitDetailsArr := strings.Split(string(commitDetailsBytes), " ") + + packReader, _, err := h.dfsAPI.DownloadFile(pod, fmt.Sprintf("/%s", commitDetailsArr[0]), sessionId, false) + if err != nil { + h.logger.Error("ref not found: ", err) + jsonhttp.BadRequest(w, &response{Message: "ref not found"}) + return + } + _, _ = w.Write([]byte(packetWrite(fmt.Sprintf("ACK %s\n", commitDetailsArr[0])))) + _, err = io.Copy(w, packReader) + if err != nil { + h.logger.Errorf("download: %v", err) + w.Header().Set("Content-Type", " application/json") + jsonhttp.InternalServerError(w, "download: "+err.Error()) + } +} + +func (h *Handler) GitReceivePack(w http.ResponseWriter, r *http.Request) { + sessionId, err := auth.GetSessionIdFromGitRequest(r) + if err != nil { + h.logger.Errorf("sessionId parse failed: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + if sessionId == "" { + h.logger.Error("sessionId not set: ", err) + jsonhttp.BadRequest(w, &response{Message: ErrUnauthorized.Error()}) + return + } + + defer r.Body.Close() + buf := new(bytes.Buffer) + if _, err := io.Copy(buf, r.Body); err != nil { + h.logger.Errorf("Error reading request body: %v", err) + http.Error(w, fmt.Sprintf("Error reading request body: %v", err), http.StatusInternalServerError) + return + } + + packIndex := bytes.Index(buf.Bytes(), []byte("PACK")) + if packIndex == -1 { + h.logger.Errorf("PACK signature not found in request body") + http.Error(w, "PACK signature not found in request body", http.StatusBadRequest) + return + } + commitDetails := strings.TrimSpace(buf.String()[:packIndex]) + commitDetailsArr := strings.Split(commitDetails, " ") + + vars := mux.Vars(r) + pod := vars["repo"] + newHash, ref := commitDetailsArr[1], commitDetailsArr[2] + + _, _, _, err = h.dfsAPI.StatusFile(pod, fmt.Sprintf("/%s", refFile), sessionId, false) + if err != nil && !errors.Is(err, file.ErrFileNotFound) { + h.logger.Errorf("Error checking commit status: %v", err) + http.Error(w, fmt.Sprintf("Error checking file status: %v", err), http.StatusInternalServerError) + return + } + if err == nil { + h.logger.Errorf("Cannot push. ref file already exists") + http.Error(w, "Cannot push", http.StatusInternalServerError) + return + } + err = h.dfsAPI.UploadFile(pod, refFile, sessionId, int64(len(newHash+" "+ref)), strings.NewReader(newHash+" "+ref), "/", "", file.MinBlockSize, 0, false, false) + if err != nil { + h.logger.Errorf("Error uploading commit: %v", err) + http.Error(w, fmt.Sprintf("Error uploading file: %v", err), http.StatusInternalServerError) + return + } + + packData := bytes.NewReader(buf.Bytes()[packIndex:]) + err = h.dfsAPI.UploadFile(pod, newHash, sessionId, int64(packData.Len()), packData, "/", "", file.MinBlockSize, 0, false, false) + if err != nil { + h.logger.Errorf("Error uploading packfile: %v", err) + http.Error(w, fmt.Sprintf("Error uploading file: %v", err), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/x-git-receive-pack-result") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(packetWrite("unpack ok\n"))) + _, _ = w.Write([]byte(packetWrite("ok " + ref + "\n"))) + _, _ = w.Write([]byte("0000")) +} + +func packetWrite(data string) string { + length := len(data) + 4 // 4 bytes for the length itself + return fmt.Sprintf("%04x%s", length, data) +} diff --git a/pkg/api/handler.go b/pkg/api/handler.go index 9186da06..90a15a3f 100644 --- a/pkg/api/handler.go +++ b/pkg/api/handler.go @@ -52,6 +52,7 @@ type Options struct { Logger logging.Logger FeedCacheSize int FeedCacheTTL string + RedundancyLevel uint8 } // New returns a new handler @@ -62,6 +63,7 @@ func New(ctx context.Context, opts *Options) (*Handler, error) { EnsConfig: opts.EnsConfig, SubscriptionConfig: opts.SubscriptionConfig, Logger: opts.Logger, + RedundancyLevel: opts.RedundancyLevel, } if opts.FeedCacheSize == 0 { opts.FeedCacheSize = defaultFeedCacheSize diff --git a/pkg/api/login_middleware.go b/pkg/api/login_middleware.go index 4a10fbfd..469bc029 100644 --- a/pkg/api/login_middleware.go +++ b/pkg/api/login_middleware.go @@ -17,6 +17,7 @@ limitations under the License. package api import ( + "errors" "net/http" "time" @@ -31,10 +32,11 @@ import ( // proceed for execution. func (h *Handler) LoginMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - sessionId, err := jwt.GetSessionIdFromToken(r) - if err != nil && err != jwt.ErrNoTokenInRequest { + + sessionId, err := jwt.GetSessionIdFromRequest(r) + if err != nil && !errors.Is(err, jwt.ErrNoTokenInRequest) { h.logger.Errorf("jwt: invalid token: %v", err) - jsonhttp.BadRequest(w, &response{Message: "jwt: invalid token"}) + jsonhttp.Unauthorized(w, &response{Message: "jwt: invalid token"}) return } @@ -46,7 +48,7 @@ func (h *Handler) LoginMiddleware(next http.Handler) http.Handler { sessionId, loginTimeout, err := cookie.GetSessionIdAndLoginTimeFromCookie(r) if err != nil { h.logger.Errorf("cookie: invalid cookie: %v", err) - jsonhttp.BadRequest(w, &response{Message: "cookie: invalid cookie: " + err.Error()}) + jsonhttp.Unauthorized(w, &response{Message: "cookie: invalid cookie: " + err.Error()}) return } @@ -54,14 +56,14 @@ func (h *Handler) LoginMiddleware(next http.Handler) http.Handler { loginTime, err := time.Parse(time.RFC3339, loginTimeout) if err != nil { h.logger.Errorf("cookie: invalid login timeout") - jsonhttp.BadRequest(w, &response{Message: "cookie: invalid login timeout"}) + jsonhttp.Unauthorized(w, &response{Message: "cookie: invalid login timeout"}) return } if loginTime.Before(time.Now()) { err = h.dfsAPI.LogoutUser(sessionId) if err == nil { h.logger.Errorf("Logging out as cookie login timeout expired") - jsonhttp.BadRequest(w, &response{Message: "logging out as cookie login timeout expired"}) + jsonhttp.Unauthorized(w, &response{Message: "logging out as cookie login timeout expired"}) return } } diff --git a/pkg/api/pod_share.go b/pkg/api/pod_share.go index c423181b..ce690356 100644 --- a/pkg/api/pod_share.go +++ b/pkg/api/pod_share.go @@ -21,10 +21,8 @@ import ( "fmt" "net/http" - "github.com/fairdatasociety/fairOS-dfs/pkg/auth" - "github.com/fairdatasociety/fairOS-dfs/cmd/common" - + "github.com/fairdatasociety/fairOS-dfs/pkg/auth" "github.com/fairdatasociety/fairOS-dfs/pkg/dfs" p "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" @@ -172,6 +170,58 @@ func (h *Handler) PodReceiveInfoHandler(w http.ResponseWriter, r *http.Request) jsonhttp.OK(w, shareInfo) } +// PodReceiveSnapshotHandler godoc +// +// @Summary Receive shared pod snapshot +// @Description PodReceiveSnapshotHandler is the api handler to receive shared pod snapshot from shared reference +// @ID pod-receive-snapshot-handler +// @Tags pod +// @Accept json +// @Produce json +// @Param sharingRef query string true "pod sharing reference" +// @Param Cookie header string true "cookie parameter" +// @Success 200 {object} pod.DirSnapShot +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /public-pod-snapshot [get] +func (h *Handler) PodReceiveSnapshotHandler(w http.ResponseWriter, r *http.Request) { + + sharingRefString := r.URL.Query().Get("sharingRef") + if sharingRefString == "" { + h.logger.Errorf("pod receive snapshot: \"sharingRef\" argument missing") + jsonhttp.BadRequest(w, "pod receive snapshot: \"sharingRef\" argument missing") + return + } + + path := r.URL.Query().Get("path") + if path == "" { + path = "/" + } + + ref, err := utils.ParseHexReference(sharingRefString) + if err != nil { + h.logger.Errorf("pod receive snapshot: invalid reference: %s", err) + jsonhttp.BadRequest(w, "pod receive snapshot: invalid reference:"+err.Error()) + return + } + + shareInfo, err := h.dfsAPI.PublicPodReceiveInfo(ref) + if err != nil { + h.logger.Errorf("pod receive snapshot: %v", err) + jsonhttp.InternalServerError(w, "pod receive snapshot: "+err.Error()) + return + } + snapshot, err := h.dfsAPI.PublicPodSnapshot(shareInfo, path) + if err != nil { + h.logger.Errorf("pod receive snapshot: %v", err) + jsonhttp.InternalServerError(w, "pod receive snapshot: "+err.Error()) + return + } + + w.Header().Set("Content-Type", " application/json") + jsonhttp.OK(w, snapshot) +} + // PodReceiveHandler godoc // // @Summary Receive shared pod diff --git a/pkg/api/user_login.go b/pkg/api/user_login.go index 36a09eac..29cb81bf 100644 --- a/pkg/api/user_login.go +++ b/pkg/api/user_login.go @@ -88,9 +88,9 @@ func (h *Handler) UserLoginV2Handler(w http.ResponseWriter, r *http.Request) { jsonhttp.NotFound(w, &response{Message: "user login: " + err.Error()}) return } - if err == u.ErrUserAlreadyLoggedIn || - err == u.ErrInvalidUserName || - err == u.ErrInvalidPassword { + if errors.Is(err, u.ErrUserAlreadyLoggedIn) || + errors.Is(err, u.ErrInvalidUserName) || + errors.Is(err, u.ErrInvalidPassword) { h.logger.Errorf("user login: %v", err) jsonhttp.BadRequest(w, &response{Message: "user login: " + err.Error()}) return @@ -114,3 +114,76 @@ func (h *Handler) UserLoginV2Handler(w http.ResponseWriter, r *http.Request) { AccessToken: loginResp.AccessToken, }) } + +// UserLoginWithSignature godoc +// +// @Summary Login User with signature +// @Description login user with signature described in https://github.com/fairDataSociety/FIPs/blob/master/text/0063-external-account-generator.md +// @ID user-login-signature +// @Tags user +// @Accept json +// @Produce json +// @Param user_request body common.UserSignatureLoginRequest true "signature and password" +// @Success 200 {object} UserLoginResponse +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Header 200 {string} Set-Cookie "fairos-dfs session" +// @Router /v2/user/login-with-signature [post] +func (h *Handler) UserLoginWithSignature(w http.ResponseWriter, r *http.Request) { + contentType := r.Header.Get("Content-Type") + if contentType != jsonContentType { + h.logger.Errorf("user login: invalid request body type") + jsonhttp.BadRequest(w, &response{Message: "user login: invalid request body type"}) + return + } + + decoder := json.NewDecoder(r.Body) + var userReq common.UserSignatureLoginRequest + err := decoder.Decode(&userReq) + if err != nil { + h.logger.Errorf("user login: could not decode arguments") + jsonhttp.BadRequest(w, &response{Message: "user login: could not decode arguments"}) + return + } + + signature := userReq.Signature + password := userReq.Password + if signature == "" { + h.logger.Errorf("user login: \"signature\" argument missing") + jsonhttp.BadRequest(w, &response{Message: "user login: \"signature\" argument missing"}) + return + } + + // login user + loginResp, err := h.dfsAPI.LoginUserWithSignature(signature, password, "") + if err != nil { + if errors.Is(err, u.ErrUserNameNotFound) { + h.logger.Errorf("user login: %v", err) + jsonhttp.NotFound(w, &response{Message: "user login: " + err.Error()}) + return + } + if errors.Is(err, u.ErrUserAlreadyLoggedIn) || + errors.Is(err, u.ErrInvalidUserName) || + errors.Is(err, u.ErrInvalidPassword) { + h.logger.Errorf("user login: %v", err) + jsonhttp.BadRequest(w, &response{Message: "user login: " + err.Error()}) + return + } + h.logger.Errorf("user login: %v", err) + jsonhttp.InternalServerError(w, &response{Message: "user login: " + err.Error()}) + return + } + err = cookie.SetSession(loginResp.UserInfo.GetSessionId(), w, h.cookieDomain) + if err != nil { + h.logger.Errorf("user login: %v", err) + jsonhttp.InternalServerError(w, &response{Message: "user login: " + err.Error()}) + return + } + addr := loginResp.UserInfo.GetAccount().GetUserAccountInfo().GetAddress() + jsonhttp.OK(w, &UserSignupResponse{ + Address: addr.Hex(), + PublicKey: loginResp.PublicKey, + Message: "user logged-in successfully", + AccessToken: loginResp.AccessToken, + }) +} diff --git a/pkg/api/user_signup.go b/pkg/api/user_signup.go index f262bd82..e7280ecc 100644 --- a/pkg/api/user_signup.go +++ b/pkg/api/user_signup.go @@ -18,6 +18,7 @@ package api import ( "encoding/json" + "errors" "net/http" "github.com/fairdatasociety/fairOS-dfs/cmd/common" @@ -90,12 +91,12 @@ func (h *Handler) UserSignupV2Handler(w http.ResponseWriter, r *http.Request) { // create user signUp, err := h.dfsAPI.CreateUserV2(user, password, mnemonic, "") if err != nil { - if err == u.ErrUserAlreadyPresent { + if errors.Is(err, u.ErrUserAlreadyPresent) { h.logger.Errorf("user signup: %v", err) jsonhttp.BadRequest(w, &response{Message: "user signup: " + err.Error()}) return } - if err == eth.ErrInsufficientBalance { + if errors.Is(err, eth.ErrInsufficientBalance) { h.logger.Errorf("user signup: %v", err) if signUp != nil { jsonhttp.PaymentRequired(w, &UserSignupResponse{ @@ -130,10 +131,11 @@ func (h *Handler) UserSignupV2Handler(w http.ResponseWriter, r *http.Request) { // send the response w.Header().Set("Content-Type", " application/json") jsonhttp.Created(w, &UserSignupResponse{ - Address: signUp.Address, - Mnemonic: mnemonic, - NameHash: "0x" + signUp.NameHash, - PublicKey: signUp.PublicKey, - Message: "user signed-up successfully", + Address: signUp.Address, + Mnemonic: mnemonic, + NameHash: "0x" + signUp.NameHash, + PublicKey: signUp.PublicKey, + Message: "user signed-up successfully", + AccessToken: signUp.AccessToken, }) } diff --git a/pkg/auth/jwt/jwt.go b/pkg/auth/jwt/jwt.go index 0cbe3c9d..8d95bf8e 100644 --- a/pkg/auth/jwt/jwt.go +++ b/pkg/auth/jwt/jwt.go @@ -1,6 +1,7 @@ package jwt import ( + "encoding/base64" "errors" "fmt" "net/http" @@ -34,7 +35,7 @@ func GenerateToken(sessionId string) (string, error) { claims := Claims{ jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), - Issuer: "test", + Issuer: "dfs", }, sessionId, } @@ -62,8 +63,8 @@ func parse(tokenStr string) (string, error) { } } -// GetSessionIdFromToken extracts sessionId from http.Request Auth header -func GetSessionIdFromToken(request *http.Request) (sessionId string, err error) { +// GetSessionIdFromRequest extracts sessionId from http.Request Auth header +func GetSessionIdFromRequest(request *http.Request) (sessionId string, err error) { authHeader := request.Header.Get("Authorization") parts := strings.Split(authHeader, "Bearer") if len(parts) != 2 { @@ -79,3 +80,45 @@ func GetSessionIdFromToken(request *http.Request) (sessionId string, err error) } return parse(tokenStr) } + +// GetSessionIdFromGitRequest extracts sessionId from http.Request Auth header for git apis +func GetSessionIdFromGitRequest(request *http.Request) (sessionId string, err error) { + authHeader := request.Header.Get("Authorization") + if authHeader == "" { + return "", ErrNoTokenInRequest + } + parts := strings.Split(authHeader, "Basic") + if len(parts) != 2 { + return "", ErrNoTokenInRequest + } + + payload, err := base64.StdEncoding.DecodeString(strings.TrimSpace(parts[1])) + if err != nil { + return "", err + } + pair := strings.SplitN(string(payload), ":", 2) + tokenStr := strings.TrimSpace(pair[1]) + if len(tokenStr) < 1 { + return "", ErrNoTokenInRequest + } + if tokenStr == "" { + return "", ErrNoTokenInRequest + } + return parse(tokenStr) +} + +// GetSessionIdFromToken extracts sessionId from an actual token +func GetSessionIdFromToken(token string) (sessionId string, err error) { + if len(token) == 0 { + return "", ErrNoTokenInRequest + } + + tokenStr := strings.TrimSpace(token) + if len(tokenStr) < 1 { + return "", ErrNoTokenInRequest + } + if tokenStr == "" { + return "", ErrNoTokenInRequest + } + return parse(tokenStr) +} diff --git a/pkg/auth/utils.go b/pkg/auth/utils.go index d9b748e7..c5deaf87 100644 --- a/pkg/auth/utils.go +++ b/pkg/auth/utils.go @@ -22,7 +22,7 @@ func GetUniqueSessionId() string { func GetSessionIdFromRequest(r *http.Request) (string, error) { sessionId, err := cookie.GetSessionIdFromCookie(r) if err != nil { - sessionId, err = jwt.GetSessionIdFromToken(r) + sessionId, err = jwt.GetSessionIdFromRequest(r) if err != nil { return "", err } @@ -30,3 +30,12 @@ func GetSessionIdFromRequest(r *http.Request) (string, error) { return sessionId, err } + +func GetSessionIdFromGitRequest(r *http.Request) (string, error) { + sessionId, err := jwt.GetSessionIdFromGitRequest(r) + if err != nil { + return "", err + } + + return sessionId, err +} diff --git a/pkg/blockstore/bee/client.go b/pkg/blockstore/bee/client.go deleted file mode 100644 index 82328517..00000000 --- a/pkg/blockstore/bee/client.go +++ /dev/null @@ -1,744 +0,0 @@ -/* -Copyright © 2020 FairOS Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bee - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "hash" - "io" - "net/http" - "time" - - "github.com/ethersphere/bee/pkg/swarm" - bmtlegacy "github.com/ethersphere/bmt/legacy" - "github.com/fairdatasociety/fairOS-dfs/pkg/logging" - lru "github.com/hashicorp/golang-lru/v2/expirable" - "github.com/sirupsen/logrus" - "golang.org/x/crypto/sha3" -) - -const ( - maxIdleConnections = 20 - maxConnectionsPerHost = 256 - requestTimeout = 6000 - chunkCacheSize = 1024 - uploadBlockCacheSize = 100 - downloadBlockCacheSize = 100 - healthUrl = "/health" - chunkUploadDownloadUrl = "/chunks" - bytesUploadDownloadUrl = "/bytes" - bzzUrl = "/bzz" - tagsUrl = "/tags" - pinsUrl = "/pins/" - _ = pinsUrl - swarmPinHeader = "Swarm-Pin" - swarmEncryptHeader = "Swarm-Encrypt" - swarmPostageBatchId = "Swarm-Postage-Batch-Id" - swarmDeferredUploadHeader = "Swarm-Deferred-Upload" - swarmTagHeader = "Swarm-Tag" - contentTypeHeader = "Content-Type" -) - -// Client is a bee http client that satisfies blockstore.Client -type Client struct { - url string - client *http.Client - hasher *bmtlegacy.Hasher - chunkCache *lru.LRU[string, []byte] - uploadBlockCache *lru.LRU[string, []byte] - downloadBlockCache *lru.LRU[string, []byte] - postageBlockId string - logger logging.Logger - isProxy bool - shouldPin bool -} - -func hashFunc() hash.Hash { - return sha3.NewLegacyKeccak256() -} - -type bytesPostResponse struct { - Reference swarm.Address `json:"reference"` -} - -type tagPostRequest struct { - Address string `json:"address"` -} - -type tagPostResponse struct { - UID uint32 `json:"uid"` - StartedAt time.Time `json:"startedAt"` - Total int64 `json:"total"` - Processed int64 `json:"processed"` - Synced int64 `json:"synced"` -} - -type beeError struct { - Code int `json:"code"` - Message string `json:"message"` -} - -// NewBeeClient creates a new client which connects to the Swarm bee node to access the Swarm network. -func NewBeeClient(apiUrl, postageBlockId string, shouldPin bool, logger logging.Logger) *Client { - p := bmtlegacy.NewTreePool(hashFunc, swarm.Branches, bmtlegacy.PoolSize) - cache := lru.NewLRU(chunkCacheSize, func(key string, value []byte) {}, 0) - uploadBlockCache := lru.NewLRU(uploadBlockCacheSize, func(key string, value []byte) {}, 0) - downloadBlockCache := lru.NewLRU(downloadBlockCacheSize, func(key string, value []byte) {}, 0) - return &Client{ - url: apiUrl, - client: createHTTPClient(), - hasher: bmtlegacy.New(p), - chunkCache: cache, - uploadBlockCache: uploadBlockCache, - downloadBlockCache: downloadBlockCache, - postageBlockId: postageBlockId, - logger: logger, - shouldPin: shouldPin, - } -} - -type chunkAddressResponse struct { - Reference swarm.Address `json:"reference"` -} - -func socResource(owner, id, sig string) string { - return fmt.Sprintf("/soc/%s/%s?sig=%s", owner, id, sig) -} - -// CheckConnection is used to check if the bee client is up and running. -func (s *Client) CheckConnection() bool { - // check if node is standalone bee - matchString := "Ethereum Swarm Bee\n" - data, _ := s.checkBee(false) - if data == matchString { - return true - } - - // check if node is gateway-proxy - data, err := s.checkBee(true) - if err != nil { - return false - } - matchString = "OK" - s.isProxy = data == matchString - - return s.isProxy -} - -func (s *Client) checkBee(isProxy bool) (string, error) { - url := s.url - if isProxy { - url += healthUrl - } - req, err := http.NewRequest(http.MethodGet, url, http.NoBody) - if err != nil { - return "", err - } - req.Close = true - // skipcq: GO-S2307 - response, err := s.Do(req) - if err != nil { - return "", err - } - - defer response.Body.Close() - data, err := io.ReadAll(response.Body) - if err != nil { - return "", err - } - return string(data), nil -} - -// Do dispatches the HTTP request to the network -func (s *Client) Do(req *http.Request) (*http.Response, error) { - return s.client.Do(req) -} - -// UploadSOC is used construct and send a Single Owner Chunk to the Swarm bee client. -func (s *Client) UploadSOC(owner, id, signature string, data []byte) (address []byte, err error) { - to := time.Now() - socResStr := socResource(owner, id, signature) - fullUrl := fmt.Sprintf(s.url + socResStr) - - req, err := http.NewRequest(http.MethodPost, fullUrl, bytes.NewBuffer(data)) - if err != nil { - return nil, err - } - req.Close = true - - // the postage block id to store the SOC chunk - req.Header.Set(swarmPostageBatchId, s.postageBlockId) - req.Header.Set(contentTypeHeader, "application/octet-stream") - req.Header.Set(swarmDeferredUploadHeader, "false") - - // TODO change this in the future when we have some alternative to pin SOC - // This is a temporary fix to force soc pinning - if s.shouldPin { - req.Header.Set(swarmPinHeader, "true") - } - - response, err := s.Do(req) - if err != nil { - return nil, err - } - - // skipcq: GO-S2307 - defer response.Body.Close() - - addrData, err := io.ReadAll(response.Body) - if err != nil { - return nil, errors.New("error uploading data") - } - - if response.StatusCode != http.StatusCreated { - var beeErr *beeError - err = json.Unmarshal(addrData, &beeErr) - if err != nil { - return nil, errors.New(string(addrData)) - } - return nil, errors.New(beeErr.Message) - } - - var addrResp *chunkAddressResponse - err = json.Unmarshal(addrData, &addrResp) - if err != nil { - return nil, err - } - - fields := logrus.Fields{ - "reference": addrResp.Reference.String(), - "duration": time.Since(to).String(), - } - 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) (address []byte, err error) { - to := time.Now() - fullUrl := fmt.Sprintf(s.url + chunkUploadDownloadUrl) - req, err := http.NewRequest(http.MethodPost, fullUrl, bytes.NewBuffer(ch.Data())) - if err != nil { - return nil, err - } - req.Close = true - - if s.shouldPin { - req.Header.Set(swarmPinHeader, "true") - } - - req.Header.Set(contentTypeHeader, "application/octet-stream") - - // the postage block id to store the chunk - req.Header.Set(swarmPostageBatchId, s.postageBlockId) - - req.Header.Set(swarmDeferredUploadHeader, "false") - - response, err := s.Do(req) - if err != nil { - return nil, err - } - // skipcq: GO-S2307 - defer response.Body.Close() - - addrData, err := io.ReadAll(response.Body) - if err != nil { - return nil, errors.New("error uploading data") - } - - if response.StatusCode != http.StatusOK { - var beeErr *beeError - err = json.Unmarshal(addrData, &beeErr) - if err != nil { - return nil, errors.New(string(addrData)) - } - return nil, errors.New(beeErr.Message) - } - - var addrResp *chunkAddressResponse - err = json.Unmarshal(addrData, &addrResp) - if err != nil { - return nil, err - } - - fields := logrus.Fields{ - "reference": ch.Address().String(), - "duration": time.Since(to).String(), - } - s.logger.WithFields(fields).Log(logrus.DebugLevel, "upload chunk: ") - - return addrResp.Reference.Bytes(), nil -} - -// DownloadChunk downloads a chunk with given address from the Swarm network -func (s *Client) DownloadChunk(ctx context.Context, address []byte) (data []byte, err error) { - to := time.Now() - addrString := swarm.NewAddress(address).String() - - path := chunkUploadDownloadUrl + "/" + addrString - fullUrl := fmt.Sprintf(s.url + path) - req, err := http.NewRequest(http.MethodGet, fullUrl, bytes.NewBuffer(data)) - if err != nil { - return nil, err - } - req.Close = true - - req = req.WithContext(ctx) - - response, err := s.Do(req) - if err != nil { - return nil, err - } - // skipcq: GO-S2307 - defer response.Body.Close() - - if response.StatusCode != http.StatusOK { - return nil, errors.New("error downloading data") - } - - data, err = io.ReadAll(response.Body) - if err != nil { - return nil, errors.New("error downloading data") - } - fields := logrus.Fields{ - "reference": addrString, - "duration": time.Since(to).String(), - } - s.logger.WithFields(fields).Log(logrus.DebugLevel, "download chunk: ") - return data, nil -} - -// 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, encrypt bool) (address []byte, err error) { - to := time.Now() - - // return the ref if this data is already in swarm - if s.inBlockCache(s.uploadBlockCache, string(data)) { - return s.getFromBlockCache(s.uploadBlockCache, string(data)), nil - } - - fullUrl := s.url + bytesUploadDownloadUrl - req, err := http.NewRequest(http.MethodPost, fullUrl, bytes.NewBuffer(data)) - if err != nil { - return nil, err - } - req.Close = true - - req.Header.Set(contentTypeHeader, "application/octet-stream") - - if s.shouldPin { - req.Header.Set(swarmPinHeader, "true") - } - - if encrypt { - req.Header.Set(swarmEncryptHeader, "true") - } - - if tag > 0 { - req.Header.Set(swarmTagHeader, fmt.Sprintf("%d", tag)) - } - - // the postage block id to store the blob - req.Header.Set(swarmPostageBatchId, s.postageBlockId) - - req.Header.Set(swarmDeferredUploadHeader, "false") - - response, err := s.Do(req) - if err != nil { - return nil, err - } - // skipcq: GO-S2307 - defer response.Body.Close() - - respData, err := io.ReadAll(response.Body) - if err != nil { - return nil, errors.New("error uploading blob") - } - - 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) - if err != nil { - return nil, fmt.Errorf("error unmarshalling response") - } - fields := logrus.Fields{ - "reference": resp.Reference.String(), - "size": len(data), - "duration": time.Since(to).String(), - } - s.logger.WithFields(fields).Log(logrus.DebugLevel, "upload blob: ") - - // add the data in cache - s.addToBlockCache(s.uploadBlockCache, string(data), resp.Reference.Bytes()) - - return resp.Reference.Bytes(), nil -} - -// DownloadBlob downloads a blob of binary data from the Swarm network. -func (s *Client) DownloadBlob(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 + bytesUploadDownloadUrl + "/" + addrString - req, err := http.NewRequest(http.MethodGet, fullUrl, http.NoBody) - if err != nil { - return nil, http.StatusNotFound, err - } - req.Close = true - - response, err := s.Do(req) - if err != nil { - return nil, http.StatusNotFound, err - } - // skipcq: GO-S2307 - defer response.Body.Close() - - respData, err := io.ReadAll(response.Body) - if err != nil { - return nil, response.StatusCode, errors.New("error downloading blob") - } - - 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 blob: ") - - // 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 -} - -// 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.Close = true - - req.Header.Set(swarmPostageBatchId, s.postageBlockId) - req.Header.Set(contentTypeHeader, "application/json") - - response, err := s.Do(req) - if err != nil { - return nil, err - } - // skipcq: GO-S2307 - defer response.Body.Close() - - 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 - } - req.Close = true - - response, err := s.Do(req) - if err != nil { - return nil, http.StatusNotFound, err - } - // skipcq: GO-S2307 - defer response.Body.Close() - - 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 { - if !s.shouldPin { - return nil - } - to := time.Now() - addrString := swarm.NewAddress(address).String() - - fullUrl := s.url + pinsUrl + addrString - req, err := http.NewRequest(http.MethodDelete, fullUrl, http.NoBody) - if err != nil { - return err - } - req.Close = true - - response, err := s.Do(req) - if err != nil { - return err - } - defer response.Body.Close() - - if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusNotFound { - respData, err := io.ReadAll(response.Body) - if err != nil { - return err - } - return fmt.Errorf("failed to unpin reference : %s", respData) - } else { - _, _ = io.Copy(io.Discard, response.Body) - } - - fields := logrus.Fields{ - "reference": addrString, - "duration": time.Since(to).String(), - } - s.logger.WithFields(fields).Log(logrus.DebugLevel, "delete chunk: ") - - return nil -} - -// CreateTag creates a tag for given address -func (s *Client) CreateTag(address []byte) (uint32, error) { - // gateway proxy does not have tags api exposed - if s.isProxy { - return 0, nil - } - to := time.Now() - - fullUrl := s.url + tagsUrl - var data []byte - var err error - if len(address) > 0 { - addrString := swarm.NewAddress(address).String() - b := &tagPostRequest{Address: addrString} - data, err = json.Marshal(b) - if err != nil { - return 0, err - } - } - req, err := http.NewRequest(http.MethodPost, fullUrl, bytes.NewBuffer(data)) - if err != nil { - return 0, err - } - req.Close = true - - response, err := s.Do(req) - if err != nil { - return 0, err - } - // skipcq: GO-S2307 - defer response.Body.Close() - - respData, err := io.ReadAll(response.Body) - if err != nil { - return 0, errors.New("error create tag") - } - - if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated { - var beeErr *beeError - err = json.Unmarshal(respData, &beeErr) - if err != nil { - return 0, errors.New(string(respData)) - } - return 0, errors.New(beeErr.Message) - } - - var resp tagPostResponse - err = json.Unmarshal(respData, &resp) - if err != nil { - return 0, fmt.Errorf("error unmarshalling response") - } - fields := logrus.Fields{ - "reference": address, - "tag": resp.UID, - "duration": time.Since(to).String(), - } - s.logger.WithFields(fields).Log(logrus.DebugLevel, "create tag: ") - - return resp.UID, nil -} - -// GetTag gets sync status of a given tag -func (s *Client) GetTag(tag uint32) (int64, int64, int64, error) { - // gateway proxy does not have tags api exposed - if s.isProxy { - return 0, 0, 0, nil - } - - to := time.Now() - - fullUrl := s.url + tagsUrl + fmt.Sprintf("/%d", tag) - - req, err := http.NewRequest(http.MethodGet, fullUrl, http.NoBody) - if err != nil { - return 0, 0, 0, err - } - req.Close = true - - response, err := s.Do(req) - if err != nil { - return 0, 0, 0, err - } - // skipcq: GO-S2307 - defer response.Body.Close() - - respData, err := io.ReadAll(response.Body) - if err != nil { - return 0, 0, 0, errors.New("error getting tag") - } - - if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated { - var beeErr *beeError - err = json.Unmarshal(respData, &beeErr) - if err != nil { - return 0, 0, 0, errors.New(string(respData)) - } - return 0, 0, 0, errors.New(beeErr.Message) - } - - var resp tagPostResponse - err = json.Unmarshal(respData, &resp) - if err != nil { - return 0, 0, 0, fmt.Errorf("error unmarshalling response") - } - fields := logrus.Fields{ - "tag": resp.UID, - "duration": time.Since(to).String(), - } - s.logger.WithFields(fields).Log(logrus.DebugLevel, "get tag: ") - - return resp.Total, resp.Processed, resp.Synced, nil -} - -// createHTTPClient for connection re-use -func createHTTPClient() *http.Client { - client := &http.Client{ - Timeout: time.Second * requestTimeout, - Transport: &http.Transport{ - MaxIdleConnsPerHost: maxIdleConnections, - MaxConnsPerHost: maxConnectionsPerHost, - }, - } - return client -} - -func (*Client) addToBlockCache(cache *lru.LRU[string, []byte], key string, value []byte) { - if cache != nil { - cache.Add(key, value) - } -} - -func (*Client) inBlockCache(cache *lru.LRU[string, []byte], key string) bool { - _, in := cache.Get(key) - return in -} - -func (*Client) getFromBlockCache(cache *lru.LRU[string, []byte], key string) []byte { - if cache != nil { - value, ok := cache.Get(key) - if ok { - return value - } - return nil - } - return nil -} diff --git a/pkg/blockstore/bee/mock/client.go b/pkg/blockstore/bee/mock/client.go deleted file mode 100644 index 3eb86b41..00000000 --- a/pkg/blockstore/bee/mock/client.go +++ /dev/null @@ -1,340 +0,0 @@ -package mock - -import ( - "context" - "crypto/ecdsa" - "crypto/rand" - "encoding/hex" - "math/big" - "net/http" - "net/http/httptest" - "sync" - "testing" - "time" - - "github.com/ethersphere/bee/pkg/storageincentives/redistribution" - - "github.com/ethereum/go-ethereum/common" - accountingmock "github.com/ethersphere/bee/pkg/accounting/mock" - "github.com/ethersphere/bee/pkg/api" - "github.com/ethersphere/bee/pkg/auth" - mockauth "github.com/ethersphere/bee/pkg/auth/mock" - "github.com/ethersphere/bee/pkg/crypto" - "github.com/ethersphere/bee/pkg/feeds" - "github.com/ethersphere/bee/pkg/log" - p2pmock "github.com/ethersphere/bee/pkg/p2p/mock" - "github.com/ethersphere/bee/pkg/pingpong" - "github.com/ethersphere/bee/pkg/postage" - mockbatchstore "github.com/ethersphere/bee/pkg/postage/batchstore/mock" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - "github.com/ethersphere/bee/pkg/postage/postagecontract" - contractMock "github.com/ethersphere/bee/pkg/postage/postagecontract/mock" - "github.com/ethersphere/bee/pkg/pss" - "github.com/ethersphere/bee/pkg/resolver" - resolverMock "github.com/ethersphere/bee/pkg/resolver/mock" - "github.com/ethersphere/bee/pkg/settlement/pseudosettle" - chequebookmock "github.com/ethersphere/bee/pkg/settlement/swap/chequebook/mock" - "github.com/ethersphere/bee/pkg/settlement/swap/erc20" - erc20mock "github.com/ethersphere/bee/pkg/settlement/swap/erc20/mock" - swapmock "github.com/ethersphere/bee/pkg/settlement/swap/mock" - statestore "github.com/ethersphere/bee/pkg/statestore/mock" - "github.com/ethersphere/bee/pkg/status" - "github.com/ethersphere/bee/pkg/steward" - "github.com/ethersphere/bee/pkg/storage" - "github.com/ethersphere/bee/pkg/storage/inmemstore" - "github.com/ethersphere/bee/pkg/storageincentives" - "github.com/ethersphere/bee/pkg/storageincentives/staking" - mock2 "github.com/ethersphere/bee/pkg/storageincentives/staking/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/ethersphere/bee/pkg/swarm" - "github.com/ethersphere/bee/pkg/topology/lightnode" - topologymock "github.com/ethersphere/bee/pkg/topology/mock" - "github.com/ethersphere/bee/pkg/tracing" - "github.com/ethersphere/bee/pkg/transaction" - "github.com/ethersphere/bee/pkg/transaction/backendmock" - transactionmock "github.com/ethersphere/bee/pkg/transaction/mock" - "github.com/ethersphere/bee/pkg/util/testutil" -) - -var ( - batchOk = make([]byte, 32) - BatchOkStr string -) - -// nolint:gochecknoinits -func init() { - _, _ = rand.Read(batchOk) - - BatchOkStr = hex.EncodeToString(batchOk) -} - -type TestServerOptions struct { - Storer api.Storer - StateStorer storage.StateStorer - Resolver resolver.Interface - Pss pss.Interface - WsPath string - WsPingPeriod time.Duration - Logger log.Logger - PreventRedirect bool - Feeds feeds.Factory - CORSAllowedOrigins []string - PostageContract postagecontract.Interface - StakingContract staking.Contract - Post postage.Service - Steward steward.Interface - WsHeaders http.Header - Authenticator auth.Authenticator - DebugAPI bool - Restricted bool - DirectUpload bool - Probe *api.Probe - - Overlay swarm.Address - PublicKey ecdsa.PublicKey - PSSPublicKey ecdsa.PublicKey - EthereumAddress common.Address - BlockTime time.Duration - P2P *p2pmock.Service - Pingpong pingpong.Interface - TopologyOpts []topologymock.Option - AccountingOpts []accountingmock.Option - ChequebookOpts []chequebookmock.Option - SwapOpts []swapmock.Option - TransactionOpts []transactionmock.Option - - BatchStore postage.Storer - SyncStatus func() (bool, error) - - BackendOpts []backendmock.Option - Erc20Opts []erc20mock.Option - BeeMode api.BeeNodeMode - RedistributionAgent *storageincentives.Agent - NodeStatus *status.Service -} - -func NewTestBeeServer(t *testing.T, o TestServerOptions) string { - t.Helper() - pk, _ := crypto.GenerateSecp256k1Key() - signer := crypto.NewDefaultSigner(pk) - - if o.Logger == nil { - o.Logger = log.Noop - } - if o.Resolver == nil { - o.Resolver = resolverMock.NewResolver() - } - if o.WsPingPeriod == 0 { - o.WsPingPeriod = 60 * time.Second - } - if o.Post == nil { - o.Post = mockpost.New() - } - if o.BatchStore == nil { - o.BatchStore = mockbatchstore.New(mockbatchstore.WithAcceptAllExistsFunc()) // default is with accept-all Exists() func - } - if o.SyncStatus == nil { - o.SyncStatus = func() (bool, error) { return true, nil } - } - if o.Authenticator == nil { - o.Authenticator = &mockauth.Auth{ - EnforceFunc: func(_, _, _ string) (bool, error) { - return true, nil - }, - } - } - - topologyDriver := topologymock.NewTopologyDriver(o.TopologyOpts...) - acc := accountingmock.NewAccounting(o.AccountingOpts...) - settlement := swapmock.New(o.SwapOpts...) - chequebook := chequebookmock.NewChequebook(o.ChequebookOpts...) - ln := lightnode.NewContainer(o.Overlay) - - transaction := transactionmock.New(o.TransactionOpts...) - - storeRecipient := statestore.NewStateStore() - recipient := pseudosettle.New(nil, o.Logger, storeRecipient, nil, big.NewInt(10000), big.NewInt(10000), o.P2P) - - if o.StateStorer == nil { - o.StateStorer = storeRecipient - } - erc20 := erc20mock.New(o.Erc20Opts...) - backend := backendmock.New(o.BackendOpts...) - - var extraOpts = api.ExtraOptions{ - TopologyDriver: topologyDriver, - Accounting: acc, - Pseudosettle: recipient, - LightNodes: ln, - Swap: settlement, - Chequebook: chequebook, - Pingpong: o.Pingpong, - BlockTime: o.BlockTime, - Storer: o.Storer, - Resolver: o.Resolver, - Pss: o.Pss, - FeedFactory: o.Feeds, - Post: o.Post, - PostageContract: o.PostageContract, - Steward: o.Steward, - SyncStatus: o.SyncStatus, - Staking: o.StakingContract, - NodeStatus: o.NodeStatus, - } - - // By default bee mode is set to full mode. - if o.BeeMode == api.UnknownMode { - o.BeeMode = api.FullMode - } - o.CORSAllowedOrigins = append(o.CORSAllowedOrigins, "*") - s := api.New(o.PublicKey, o.PSSPublicKey, o.EthereumAddress, o.Logger, transaction, o.BatchStore, o.BeeMode, true, true, backend, o.CORSAllowedOrigins, inmemstore.New()) - testutil.CleanupCloser(t, s) - - s.SetP2P(o.P2P) - - if o.RedistributionAgent == nil { - o.RedistributionAgent, _ = createRedistributionAgentService(t, o.Overlay, o.StateStorer, erc20, transaction, backend, o.BatchStore) - s.SetRedistributionAgent(o.RedistributionAgent) - } - testutil.CleanupCloser(t, o.RedistributionAgent) - - s.SetSwarmAddress(&o.Overlay) - s.SetProbe(o.Probe) - - noOpTracer, tracerCloser, _ := tracing.NewTracer(&tracing.Options{ - Enabled: false, - }) - testutil.CleanupCloser(t, tracerCloser) - - s.Configure(signer, o.Authenticator, noOpTracer, api.Options{ - CORSAllowedOrigins: o.CORSAllowedOrigins, - WsPingPeriod: o.WsPingPeriod, - Restricted: o.Restricted, - }, extraOpts, 1, erc20) - - if o.DebugAPI { - s.MountTechnicalDebug() - s.MountDebug(false) - } else { - s.MountAPI() - } - - ts := httptest.NewServer(s) - t.Cleanup(ts.Close) - return ts.URL -} - -func createRedistributionAgentService( - t *testing.T, - addr swarm.Address, - storer storage.StateStorer, - erc20Service erc20.Service, - tranService transaction.Service, - backend storageincentives.ChainBackend, - chainStateGetter postage.ChainStateGetter, -) (*storageincentives.Agent, error) { - t.Helper() - - const blocksPerRound uint64 = 12 - const blocksPerPhase uint64 = 4 - postageContract := contractMock.New(contractMock.WithExpiresBatchesFunc(func(context.Context) error { - return nil - }), - ) - stakingContract := mock2.New(mock2.WithIsFrozen(func(context.Context, uint64) (bool, error) { - return true, nil - })) - contract := &mockContract{} - - return storageincentives.New( - addr, - common.Address{}, - backend, - contract, - postageContract, - stakingContract, - mockstorer.NewReserve(), - func() bool { return true }, - time.Millisecond*10, - blocksPerRound, - blocksPerPhase, - storer, - chainStateGetter, - erc20Service, - tranService, - &mockHealth{}, - log.Noop, - ) -} - -type contractCall int - -func (c contractCall) String() string { - switch c { - case isWinnerCall: - return "isWinnerCall" - case revealCall: - return "revealCall" - case commitCall: - return "commitCall" - case claimCall: - return "claimCall" - } - return "unknown" -} - -const ( - isWinnerCall contractCall = iota - revealCall - commitCall - claimCall -) - -type mockContract struct { - callsList []contractCall - mtx sync.Mutex -} - -func (m *mockContract) Fee(ctx context.Context, txHash common.Hash) *big.Int { - return big.NewInt(1000) -} - -func (m *mockContract) ReserveSalt(context.Context) ([]byte, error) { - return nil, nil -} - -func (m *mockContract) IsPlaying(context.Context, uint8) (bool, error) { - return true, nil -} - -func (m *mockContract) IsWinner(context.Context) (bool, error) { - m.mtx.Lock() - defer m.mtx.Unlock() - m.callsList = append(m.callsList, isWinnerCall) - return false, nil -} - -func (m *mockContract) Claim(context.Context, redistribution.ChunkInclusionProofs) (common.Hash, error) { - m.mtx.Lock() - defer m.mtx.Unlock() - m.callsList = append(m.callsList, claimCall) - return common.Hash{}, nil -} - -func (m *mockContract) Commit(context.Context, []byte, uint64) (common.Hash, error) { - m.mtx.Lock() - defer m.mtx.Unlock() - m.callsList = append(m.callsList, commitCall) - return common.Hash{}, nil -} - -func (m *mockContract) Reveal(context.Context, uint8, []byte, []byte) (common.Hash, error) { - m.mtx.Lock() - defer m.mtx.Unlock() - m.callsList = append(m.callsList, revealCall) - return common.Hash{}, nil -} - -type mockHealth struct{} - -func (m *mockHealth) IsHealthy() bool { return true } diff --git a/pkg/blockstore/client.go b/pkg/blockstore/client.go deleted file mode 100644 index 97fcc943..00000000 --- a/pkg/blockstore/client.go +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright © 2020 FairOS Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package blockstore - -import ( - "context" - - "github.com/ethersphere/bee/pkg/swarm" -) - -// Client is the interface for block store -type Client interface { - CheckConnection() bool - UploadSOC(owner string, id string, signature string, data []byte) (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/batch.go b/pkg/collection/batch.go index 6e632412..c7ab04a5 100644 --- a/pkg/collection/batch.go +++ b/pkg/collection/batch.go @@ -17,6 +17,7 @@ limitations under the License. package collection import ( + "bytes" "context" "errors" "fmt" @@ -76,11 +77,11 @@ func (b *Batch) Put(key string, value []byte, apnd, memory bool) error { } stringKey = fmt.Sprintf("%020d", i) } else if b.idx.indexType == BytesIndex { - ref, err := b.idx.client.UploadBlob(value, 0, true) + ref, err := b.idx.client.UploadBlob(0, "", "0", false, true, bytes.NewReader(value)) if err != nil { // skipcq: TCV-001 return err } - value = ref + value = ref.Bytes() } return b.idx.addOrUpdateStringEntry(ctx, b.memDb, stringKey, b.idx.indexType, value, memory, apnd) } diff --git a/pkg/collection/batch_test.go b/pkg/collection/batch_test.go index 981eb98e..ccf47e19 100644 --- a/pkg/collection/batch_test.go +++ b/pkg/collection/batch_test.go @@ -18,19 +18,22 @@ package collection_test import ( "bytes" + "fmt" "io" "testing" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + + "github.com/asabya/swarm-blockstore/bee" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/sirupsen/logrus" "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/collection" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -45,7 +48,7 @@ func TestBatchIndex(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) acc := account.New(logger) ai := acc.GetUserAccountInfo() _, _, err := acc.CreateUserAccount("") diff --git a/pkg/collection/document.go b/pkg/collection/document.go index 0bf83a00..26e1f4fb 100644 --- a/pkg/collection/document.go +++ b/pkg/collection/document.go @@ -33,10 +33,12 @@ import ( "strings" "sync" + "github.com/ethersphere/bee/v2/pkg/swarm" + + blockstore "github.com/asabya/swarm-blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/taskmanager" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -675,7 +677,7 @@ func (d *Document) Put(dbName string, doc []byte) error { } // upload the document - ref, err := d.client.UploadBlob(doc, 0, true) + ref, err := d.client.UploadBlob(0, "", "0", false, true, bytes.NewReader(doc)) if err != nil { // skipcq: TCV-001 d.logger.Errorf("inserting in to document db: ", err.Error()) return err @@ -711,7 +713,7 @@ func (d *Document) Put(dbName string, doc []byte) error { return err } embeddingHex := hex.EncodeToString(buf.Bytes()) - err := index.Put(embeddingHex, ref, StringIndex, true) + err := index.Put(embeddingHex, ref.Bytes(), StringIndex, true) if err != nil { // skipcq: TCV-001 d.logger.Errorf("inserting in to document db: ", err.Error()) return err @@ -721,7 +723,7 @@ func (d *Document) Put(dbName string, doc []byte) error { if field == DefaultIndexFieldName { apnd = false } - err := index.Put(v.(string), ref, StringIndex, apnd) + err := index.Put(v.(string), ref.Bytes(), StringIndex, apnd) if err != nil { // skipcq: TCV-001 d.logger.Errorf("inserting in to document db: ", err.Error()) return err @@ -732,7 +734,7 @@ func (d *Document) Put(dbName string, doc []byte) error { for keyField, vf := range valMap { valueField := vf.(string) mapField := keyField + valueField - err := index.Put(mapField, ref, StringIndex, true) + err := index.Put(mapField, ref.Bytes(), StringIndex, true) if err != nil { // skipcq: TCV-001 d.logger.Errorf("inserting in to document db: ", err.Error()) return err @@ -742,7 +744,7 @@ func (d *Document) Put(dbName string, doc []byte) error { case ListIndex: valList := v.([]interface{}) for _, listVal := range valList { - err := index.Put(listVal.(string), ref, StringIndex, true) + err := index.Put(listVal.(string), ref.Bytes(), StringIndex, true) if err != nil { d.logger.Errorf("inserting in to document db: ", err.Error()) return err @@ -752,7 +754,7 @@ func (d *Document) Put(dbName string, doc []byte) error { case NumberIndex: val := v.(float64) // valStr := strconv.FormatFloat(val, 'f', 6, 64) - err := index.PutNumber(val, ref, NumberIndex, true) + err := index.PutNumber(val, ref.Bytes(), NumberIndex, true) if err != nil { // skipcq: TCV-001 d.logger.Errorf("inserting in to document db: ", err.Error()) return err @@ -791,7 +793,13 @@ func (d *Document) Get(dbName, id, podPassword string) ([]byte, error) { } if idIndex.mutable { - data, _, err := d.client.DownloadBlob(reference[0]) + r, _, err := d.client.DownloadBlob(swarm.NewAddress(reference[0])) + if err != nil { // skipcq: TCV-001 + d.logger.Errorf("getting from document db: ", err.Error()) + return nil, err + } + defer r.Close() + data, err := io.ReadAll(r) if err != nil { // skipcq: TCV-001 d.logger.Errorf("getting from document db: ", err.Error()) return nil, err @@ -849,12 +857,18 @@ func (d *Document) Del(dbName, id string) error { return nil } - data, _, err := d.client.DownloadBlob(refs[0]) + r, _, err := d.client.DownloadBlob(swarm.NewAddress(refs[0])) if err != nil { // skipcq: TCV-001 d.logger.Errorf("deleting from document db: ", err.Error()) return err } + defer r.Close() + data, err := io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + d.logger.Errorf("deleting from document db: ", err.Error()) + return err + } var t interface{} err = json.Unmarshal(data, &t) if err != nil { // skipcq: TCV-001 @@ -915,7 +929,7 @@ func (d *Document) Del(dbName, id string) error { } // delete the original data (unpin) - err = d.client.DeleteReference(refs[0]) + err = d.client.DeleteReference(swarm.NewAddress(refs[0])) if err != nil { // skipcq: TCV-001 d.logger.Errorf("deleting from document db: ", err.Error()) return err @@ -1504,12 +1518,18 @@ func (d *Document) DocBatchPut(docBatch *DocBatch, doc []byte, index int64) erro if err == nil { // skipcq: TCV-001 // found a doc with the same id, so remove it and all the indexes if len(refs) > 0 { - data, _, err := d.client.DownloadBlob(refs[0]) + r, _, err := d.client.DownloadBlob(swarm.NewAddress(refs[0])) if err != nil { d.logger.Errorf("inserting in batch: ", err.Error()) return err } + defer r.Close() + data, err := io.ReadAll(r) + if err != nil { + d.logger.Errorf("inserting in batch: ", err.Error()) + return err + } var t interface{} err = json.Unmarshal(data, &t) if err != nil { @@ -1564,7 +1584,7 @@ func (d *Document) DocBatchPut(docBatch *DocBatch, doc []byte, index int64) erro } } - err = d.client.DeleteReference(refs[0]) + err = d.client.DeleteReference(swarm.NewAddress(refs[0])) if err != nil { d.logger.Errorf("inserting in batch: ", err.Error()) return err @@ -1575,11 +1595,12 @@ func (d *Document) DocBatchPut(docBatch *DocBatch, doc []byte, index int64) erro } // upload the document - ref, err = d.client.UploadBlob(doc, 0, true) + addr, err := d.client.UploadBlob(0, "", "0", false, true, bytes.NewReader(doc)) if err != nil { // skipcq: TCV-001 d.logger.Errorf("inserting in batch: ", err.Error()) return err } + ref = addr.Bytes() } else { // skipcq: TCV-001 // store the seek index of the document instead of its reference b := make([]byte, binary.MaxVarintLen64) @@ -1785,7 +1806,13 @@ func newEntryTask(c blockstore.Client, allData *[][]byte, ref []byte, mtx sync.L // Execute func (et *entryTask) Execute(context.Context) error { - data, _, err := et.c.DownloadBlob(et.ref) + r, _, err := et.c.DownloadBlob(swarm.NewAddress(et.ref)) + if err != nil { + return err + } + defer r.Close() + + data, err := io.ReadAll(r) if err != nil { return err } diff --git a/pkg/collection/document_test.go b/pkg/collection/document_test.go index b224be23..6e092b68 100644 --- a/pkg/collection/document_test.go +++ b/pkg/collection/document_test.go @@ -20,17 +20,20 @@ import ( "context" "encoding/json" "errors" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + + "github.com/asabya/swarm-blockstore/bee" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/sirupsen/logrus" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/collection" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" f "github.com/fairdatasociety/fairOS-dfs/pkg/file" @@ -61,7 +64,7 @@ func TestDocumentStore(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) acc := account.New(logger) ai := acc.GetUserAccountInfo() _, _, err := acc.CreateUserAccount("") diff --git a/pkg/collection/index.go b/pkg/collection/index.go index cef4a848..ecc8ac6b 100644 --- a/pkg/collection/index.go +++ b/pkg/collection/index.go @@ -17,17 +17,21 @@ limitations under the License. package collection import ( + "bytes" "context" "encoding/json" "errors" "fmt" + "io" "net/http" "runtime" "sync/atomic" "time" + "github.com/ethersphere/bee/v2/pkg/swarm" + + blockstore "github.com/asabya/swarm-blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -134,19 +138,19 @@ func CreateIndex(podName, collectionName, indexName, encryptionPassword string, return ErrManifestUnmarshall } - ref, err := client.UploadBlob(data, 0, true) + ref, err := client.UploadBlob(0, "", "0", false, true, bytes.NewReader(data)) if err != nil { // skipcq: TCV-001 return ErrManifestUnmarshall } if string(oldData) == utils.DeletedFeedMagicWord { // skipcq: TCV-001 - err = fd.UpdateFeed(user, topic, ref, []byte(encryptionPassword), false) + err = fd.UpdateFeed(user, topic, ref.Bytes(), []byte(encryptionPassword), false) if err != nil { return ErrManifestCreate } return nil } - err = fd.CreateFeed(user, topic, ref, []byte(encryptionPassword)) + err = fd.CreateFeed(user, topic, ref.Bytes(), []byte(encryptionPassword)) if err != nil { // skipcq: TCV-001 return ErrManifestCreate } @@ -275,7 +279,7 @@ func (idx *Index) loadManifest(manifestPath, encryptionPassword string) (*Manife if err != nil { // skipcq: TCV-001 return nil, ErrNoManifestFound } - data, respCode, err := idx.client.DownloadBlob(refData) + r, respCode, err := idx.client.DownloadBlob(swarm.NewAddress(refData)) if err != nil { // skipcq: TCV-001 return nil, ErrNoManifestFound } @@ -283,6 +287,13 @@ func (idx *Index) loadManifest(manifestPath, encryptionPassword string) (*Manife return nil, ErrNoManifestFound } + defer r.Close() + + data, err := io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + return nil, ErrManifestUnmarshall + } + var manifest Manifest err = json.Unmarshal(data, &manifest) if err != nil { // skipcq: TCV-001 @@ -300,13 +311,13 @@ func (idx *Index) updateManifest(manifest *Manifest, encryptionPassword string) return ErrManifestUnmarshall } - ref, err := idx.client.UploadBlob(data, 0, true) + ref, err := idx.client.UploadBlob(0, "", "0", false, true, bytes.NewReader(data)) if err != nil { // skipcq: TCV-001 return ErrManifestUnmarshall } topic := utils.HashString(manifest.Name) - err = idx.feed.UpdateFeed(idx.user, topic, ref, []byte(encryptionPassword), false) + err = idx.feed.UpdateFeed(idx.user, topic, ref.Bytes(), []byte(encryptionPassword), false) if err != nil { // skipcq: TCV-001 return ErrManifestCreate } @@ -322,7 +333,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) + ref, err := idx.client.UploadBlob(0, "", "0", false, true, bytes.NewReader(data)) // TODO: once the tags issue is fixed i bytes. // remove the error string check if err != nil { // skipcq: TCV-001 @@ -332,14 +343,14 @@ func (idx *Index) storeManifest(manifest *Manifest, encryptionPassword string) e topic := utils.HashString(manifest.Name) _, _, err = idx.feed.GetFeedData(topic, idx.user, []byte(encryptionPassword), false) if err == nil || errors.Is(err, file.ErrDeletedFeed) { - err = idx.feed.UpdateFeed(idx.user, topic, ref, []byte(encryptionPassword), false) + err = idx.feed.UpdateFeed(idx.user, topic, ref.Bytes(), []byte(encryptionPassword), false) if err != nil { // skipcq: TCV-001 idx.logger.Errorf("updateFeed failed in storeManifest : %s", err.Error()) return ErrManifestCreate } return nil } - err = idx.feed.CreateFeed(idx.user, topic, ref, []byte(encryptionPassword)) + err = idx.feed.CreateFeed(idx.user, topic, ref.Bytes(), []byte(encryptionPassword)) if err != nil { // skipcq: TCV-001 idx.logger.Errorf("createFeed failed in storeManifest : %s", err.Error()) return ErrManifestCreate @@ -380,7 +391,13 @@ func getRootManifestOfIndex(actualIndexName, encryptionPassword string, fd *feed if err != nil { return nil } - data, _, err := client.DownloadBlob(addr) + r, _, err := client.DownloadBlob(swarm.NewAddress(addr)) + if err != nil { + return nil + } + defer r.Close() + + data, err := io.ReadAll(r) if err != nil { return nil } diff --git a/pkg/collection/index_api_test.go b/pkg/collection/index_api_test.go index 4af8bfa3..45faff42 100644 --- a/pkg/collection/index_api_test.go +++ b/pkg/collection/index_api_test.go @@ -19,20 +19,24 @@ package collection_test import ( "bytes" "errors" + "fmt" "io" "net/http" "testing" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + "github.com/ethersphere/bee/v2/pkg/swarm" + + "github.com/asabya/swarm-blockstore/bee" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/sirupsen/logrus" "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/collection" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -47,7 +51,7 @@ func TestIndexAPI(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) acc := account.New(logger) ai := acc.GetUserAccountInfo() _, _, err := acc.CreateUserAccount("") @@ -153,11 +157,11 @@ func TestIndexAPI(t *testing.T) { } func addDoc(t *testing.T, key string, value []byte, index *collection.Index, client *bee.Client, apnd bool) { - ref, err := client.UploadBlob(value, 0, false) + ref, err := client.UploadBlob(0, "", "0", false, false, bytes.NewReader(value)) if err != nil { t.Fatalf("could not add doc %s:%s, %v", key, value, err) } - err = index.Put(key, ref, collection.StringIndex, apnd) + err = index.Put(key, ref.Bytes(), collection.StringIndex, apnd) if err != nil { t.Fatalf("could not add doc in index: %s:%s, %v", key, ref, err) } @@ -171,13 +175,18 @@ func getDoc(t *testing.T, key string, index *collection.Index, client *bee.Clien } t.Fatal(err) } - data, respCode, err := client.DownloadBlob(ref[0]) + r, respCode, err := client.DownloadBlob(swarm.NewAddress(ref[0])) if err != nil { t.Fatal(err) } if respCode != http.StatusOK { t.Fatalf("invalid response code") } + defer r.Close() + data, err := io.ReadAll(r) + if err != nil { + t.Fatal(err) + } return data } func getAllDocs(t *testing.T, key string, index *collection.Index, client *bee.Client) [][]byte { @@ -191,26 +200,36 @@ func getAllDocs(t *testing.T, key string, index *collection.Index, client *bee.C var data [][]byte for _, ref := range refs { - buf, respCode, err := client.DownloadBlob(ref) + r, respCode, err := client.DownloadBlob(swarm.NewAddress(ref)) if err != nil { t.Fatal(err) } if respCode != http.StatusOK { t.Fatalf("invalid response code") } + buf, err := io.ReadAll(r) + if err != nil { + t.Fatal(err) + } + r.Close() data = append(data, buf) } return data } func getValue(t *testing.T, ref []byte, client *bee.Client) []byte { - data, respCode, err := client.DownloadBlob(ref) + r, respCode, err := client.DownloadBlob(swarm.NewAddress(ref)) if err != nil { t.Fatal(err) } if respCode != http.StatusOK { t.Fatalf("invalid response code") } + defer r.Close() + data, err := io.ReadAll(r) + if err != nil { + t.Fatal(err) + } return data } @@ -219,13 +238,18 @@ func delDoc(t *testing.T, key string, index *collection.Index, client *bee.Clien if err != nil { t.Fatal(err) } - data, respCode, err := client.DownloadBlob(ref[0]) + r, respCode, err := client.DownloadBlob(swarm.NewAddress(ref[0])) if err != nil { t.Fatal(err) } if respCode != http.StatusOK { t.Fatalf("invalid response code") } + defer r.Close() + data, err := io.ReadAll(r) + if err != nil { + t.Fatal(err) + } return data } @@ -289,11 +313,11 @@ func addBatchDocs(t *testing.T, batch *collection.Batch, client *bee.Client) map // add the documents for k, v := range kvMap { - ref, err := client.UploadBlob(v, 0, false) + ref, err := client.UploadBlob(0, "", "0", false, false, bytes.NewReader(v)) if err != nil { t.Fatalf("could not add doc %s:%s, %v", k, ref, err) } - err = batch.Put(k, ref, false, false) + err = batch.Put(k, ref.Bytes(), false, false) if err != nil { t.Fatal(err) } diff --git a/pkg/collection/index_test.go b/pkg/collection/index_test.go index b7ced4bd..577a436e 100644 --- a/pkg/collection/index_test.go +++ b/pkg/collection/index_test.go @@ -20,20 +20,24 @@ import ( "bytes" "encoding/json" "errors" + "fmt" "io" "strconv" "testing" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + "github.com/ethersphere/bee/v2/pkg/swarm" + + blockstore "github.com/asabya/swarm-blockstore" + "github.com/asabya/swarm-blockstore/bee" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/sirupsen/logrus" "github.com/fairdatasociety/fairOS-dfs/pkg/pod" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/collection" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -49,7 +53,7 @@ func TestIndex(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) acc := account.New(logger) ai := acc.GetUserAccountInfo() _, _, err := acc.CreateUserAccount("") @@ -212,10 +216,15 @@ func isIndexPresent(t *testing.T, podName, collectionName, indexName, encryption topic := utils.HashString(actualIndexName) _, addr, err := fd.GetFeedData(topic, user, []byte(encryptionPassword), false) if err == nil && len(addr) != 0 { - data, _, err := client.DownloadBlob(addr) + r, _, err := client.DownloadBlob(swarm.NewAddress(addr)) if err != nil { return false } + defer r.Close() + data, err := io.ReadAll(r) + if err != nil { + t.Fatal(err) + } var manifest collection.Manifest err = json.Unmarshal(data, &manifest) if err != nil { diff --git a/pkg/collection/iterator_test.go b/pkg/collection/iterator_test.go index 41c42b0c..502d03db 100644 --- a/pkg/collection/iterator_test.go +++ b/pkg/collection/iterator_test.go @@ -25,16 +25,18 @@ import ( "strconv" "testing" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + + blockstore "github.com/asabya/swarm-blockstore" + "github.com/asabya/swarm-blockstore/bee" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/sirupsen/logrus" "github.com/fairdatasociety/fairOS-dfs/pkg/pod" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/collection" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -50,7 +52,7 @@ func TestIndexIterator(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) acc := account.New(logger) ai := acc.GetUserAccountInfo() _, _, err := acc.CreateUserAccount("") diff --git a/pkg/collection/kv.go b/pkg/collection/kv.go index 5fc92ea1..908a0130 100644 --- a/pkg/collection/kv.go +++ b/pkg/collection/kv.go @@ -25,8 +25,10 @@ import ( "strings" "sync" + "github.com/ethersphere/bee/v2/pkg/swarm" + + blockstore "github.com/asabya/swarm-blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" @@ -265,11 +267,11 @@ 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) + ref, err := kv.client.UploadBlob(0, "", "0", false, true, bytes.NewReader(value)) if err != nil { // skipcq: TCV-001 return err } - return table.index.Put(key, ref, StringIndex, false) + return table.index.Put(key, ref.Bytes(), StringIndex, false) default: // skipcq: TCV-001 return ErrKVInvalidIndexType } @@ -288,10 +290,17 @@ func (kv *KeyValue) KVGet(name, key string) ([]string, []byte, error) { return nil, nil, err } if table.indexType == BytesIndex { - data, _, err := kv.client.DownloadBlob(value[0]) + r, _, err := kv.client.DownloadBlob(swarm.NewAddress(value[0])) + if err != nil { // skipcq: TCV-001 + return nil, nil, err + } + + defer r.Close() + data, err := io.ReadAll(r) if err != nil { // skipcq: TCV-001 return nil, nil, err } + value[0] = data } return table.columns, value[0], nil diff --git a/pkg/collection/kv_test.go b/pkg/collection/kv_test.go index f5b773cf..a785b0b3 100644 --- a/pkg/collection/kv_test.go +++ b/pkg/collection/kv_test.go @@ -29,13 +29,15 @@ import ( "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + + "github.com/asabya/swarm-blockstore/bee" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/sirupsen/logrus" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/collection" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -65,7 +67,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -103,7 +106,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -137,7 +141,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -176,7 +181,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -215,7 +221,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -249,7 +256,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -341,7 +349,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -373,7 +382,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -393,7 +403,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -422,7 +433,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -441,7 +453,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -488,7 +501,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -539,7 +553,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -578,7 +593,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -605,7 +621,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -670,7 +687,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -693,7 +711,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -726,7 +745,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -750,7 +770,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -816,7 +837,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) defer fd.CommitFeeds() user := acc.GetAddress(account.UserAccountIndex) @@ -878,7 +900,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -911,7 +934,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, 500, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -964,7 +988,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1028,7 +1053,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1109,7 +1135,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1206,7 +1233,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1250,7 +1278,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1295,7 +1324,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1359,7 +1389,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1417,7 +1448,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1458,7 +1490,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1489,7 +1522,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1516,7 +1550,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1543,7 +1578,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) @@ -1570,7 +1606,8 @@ func TestKeyValueStore(t *testing.T) { PreventRedirect: true, Post: mockpost.New(mockpost.WithAcceptAll()), }) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + fd := feed.New(acc.GetUserAccountInfo(), mockClient, -1, 0, logger) user := acc.GetAddress(account.UserAccountIndex) kvStore := collection.NewKeyValueStore("pod1", fd, ai, user, mockClient, logger) diff --git a/pkg/dfs/act_api.go b/pkg/dfs/act_api.go new file mode 100644 index 00000000..a23965c4 --- /dev/null +++ b/pkg/dfs/act_api.go @@ -0,0 +1,194 @@ +package dfs + +import ( + "crypto/ecdsa" + + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" + + "github.com/ethersphere/bee/v2/pkg/swarm" + "github.com/fairdatasociety/fairOS-dfs/pkg/act" +) + +func (a *API) CreateGranteePublicKey(sessionId, actName string, publicKey *ecdsa.PublicKey) error { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return ErrUserNotLoggedIn + } + actList := ui.GetACTList() + _, err := actList.CreateUpdateACT(actName, publicKey, nil) + return err +} + +func (a *API) GrantRevokeGranteePublicKey(sessionId, actName string, publicKeyGrant, publicKeyRevoke *ecdsa.PublicKey) error { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return ErrUserNotLoggedIn + } + + actList := ui.GetACTList() + _, err := actList.CreateUpdateACT(actName, publicKeyGrant, publicKeyRevoke) + return err +} + +func (a *API) ListGrantees(sessionId, actName string) ([]string, error) { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return nil, ErrUserNotLoggedIn + } + + actList := ui.GetACTList() + return actList.GetGrantees(actName) +} + +func (a *API) ACTPodShare(sessionId, podName, actName string) (*act.Content, error) { + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return nil, ErrUserNotLoggedIn + } + + actList := ui.GetACTList() + address, err := ui.GetPod().PodShare(podName, "") + if err != nil { + return nil, err + } + + addr, err := swarm.ParseHexAddress(address) + if err != nil { + return nil, err + } + + return actList.GrantAccess(actName, addr) +} + +func (a *API) OpenACTPod(sessionId, actName string) error { + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return ErrUserNotLoggedIn + } + + actList := ui.GetACTList() + addr, err := actList.GetPodAccess(actName) + if err != nil { + return err + } + + info, err := ui.GetPod().ReceivePodInfo(utils.NewReference(addr.Bytes())) + if err != nil { + return err + } + + _, err = ui.GetPod().OpenActPod(info, actName) + if err != nil { + return err + } + + return err +} + +func (a *API) GetACTs(sessionId string) (act.List, error) { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return nil, ErrUserNotLoggedIn + } + + actList := ui.GetACTList() + return actList.GetList() +} +func (a *API) SaveACTPod(sessionId, actName string, c *act.Content) error { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return ErrUserNotLoggedIn + } + + actList := ui.GetACTList() + return actList.SaveGrantedPod(actName, c) +} + +func (a *API) GetACTContents(sessionId, actName string) ([]*act.Content, error) { + // get the loggedin user information + ui := a.users.GetLoggedInUserInfo(sessionId) + if ui == nil { + return nil, ErrUserNotLoggedIn + } + + actList := ui.GetACTList() + + return actList.GetContentList(actName) +} + +//func (a *API) GrantRevokeGrantee(sessionId, grantUser, revokeUser, actName string) error { +// // get the loggedin user information +// ui := a.users.GetLoggedInUserInfo(sessionId) +// if ui == nil { +// return ErrUserNotLoggedIn +// } +// grantList := make([]*ecdsa.PublicKey, 1) +// revokeList := make([]*ecdsa.PublicKey, 1) +// +// actList := ui.GetACTList() +// act, err := actList.GetACT(actName) +// if err != nil { // skipcq: TCV-001 +// return err +// } +// historyRef, granteeListRef := act.HistoryRef, act.GranteesRef +// if grantUser == "" && revokeUser == "" { +// return fmt.Errorf("grant or revoke user required") +// } +// if grantUser != "" { +// publicKeyGrant, _, err := a.users.GetUserInfo(grantUser) +// if err != nil { // skipcq: TCV-001 +// return err +// } +// if publicKeyGrant == nil { +// return fmt.Errorf("public key not found") +// } +// grantList[0] = publicKeyGrant +// } +// if revokeUser != "" { +// publicKeyRevoke, _, err := a.users.GetUserInfo(revokeUser) +// if err != nil { // skipcq: TCV-001 +// return err +// } +// if publicKeyRevoke == nil { +// return fmt.Errorf("public key not found") +// } +// revokeList[0] = publicKeyRevoke +// } +// +// swarmAct := ui.GetACT() +// createResp, err := swarmAct.RevokeGrant(a.context, granteeListRef, historyRef, grantList, revokeList) +// if err != nil { // skipcq: TCV-001 +// return err +// } +// _, err = actList.CreateUpdateACT(actName, createResp.HistoryReference, createResp.Reference) +// return err +//} + +//func (a *API) CreateGrantee(sessionId, user, actName string) error { +// // get the loggedin user information +// ui := a.users.GetLoggedInUserInfo(sessionId) +// if ui == nil { +// return ErrUserNotLoggedIn +// } +// +// publicKey, _, err := a.users.GetUserInfo(user) +// if err != nil { // skipcq: TCV-001 +// return err +// } +// if publicKey == nil { +// return fmt.Errorf("public key not found") +// } +// +// act := ui.GetACT() +// addList := []*ecdsa.PublicKey{publicKey} +// createResp, err := act.CreateGrantee(a.context, swarm.ZeroAddress, addList) +// +// // TODO save in ACT LIST +// _ = createResp +// return err +//} diff --git a/pkg/dfs/api.go b/pkg/dfs/api.go index 4be87798..c3ff06a7 100644 --- a/pkg/dfs/api.go +++ b/pkg/dfs/api.go @@ -19,11 +19,12 @@ package dfs import ( "context" "errors" + "fmt" "io" "time" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + blockstore "github.com/asabya/swarm-blockstore" + "github.com/asabya/swarm-blockstore/bee" "github.com/fairdatasociety/fairOS-dfs/pkg/contracts" ethClient "github.com/fairdatasociety/fairOS-dfs/pkg/ensm/eth" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -59,6 +60,7 @@ type Options struct { Logger logging.Logger FeedCacheSize int FeedCacheTTL time.Duration + RedundancyLevel uint8 } // NewDfsAPI is the main entry point for the df controller. @@ -72,7 +74,7 @@ func NewDfsAPI(ctx context.Context, opts *Options) (*API, error) { } return nil, errEthClient } - c := bee.NewBeeClient(opts.BeeApiEndpoint, opts.Stamp, true, logger) + c := bee.NewBeeClient(opts.BeeApiEndpoint, bee.WithStamp(opts.Stamp), bee.WithRedundancy(fmt.Sprintf("%d", opts.RedundancyLevel))) if !c.CheckConnection() { logger.Errorf("dfs: bee client initialisation failed") return nil, errBeeClient diff --git a/pkg/dfs/pod_api.go b/pkg/dfs/pod_api.go index 1fad4715..972b7c03 100644 --- a/pkg/dfs/pod_api.go +++ b/pkg/dfs/pod_api.go @@ -27,6 +27,10 @@ import ( "path/filepath" "strconv" "strings" + "sync" + "time" + + "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/fairdatasociety/fairOS-dfs/pkg/account" c "github.com/fairdatasociety/fairOS-dfs/pkg/collection" @@ -247,7 +251,7 @@ func (a *API) PodReceiveInfo(sessionId string, ref utils.Reference) (*pod.ShareI // PublicPodReceiveInfo receives the pod information for a public pod func (a *API) PublicPodReceiveInfo(ref utils.Reference) (*pod.ShareInfo, error) { - data, resp, err := a.client.DownloadBlob(ref.Bytes()) + r, resp, err := a.client.DownloadBlob(swarm.NewAddress(ref.Bytes())) if err != nil { // skipcq: TCV-001 return nil, err } @@ -255,7 +259,12 @@ func (a *API) PublicPodReceiveInfo(ref utils.Reference) (*pod.ShareInfo, error) if resp != http.StatusOK { // skipcq: TCV-001 return nil, fmt.Errorf("ReceivePodInfo: could not download blob") } + defer r.Close() + data, err := io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + return nil, err + } var shareInfo *pod.ShareInfo err = json.Unmarshal(data, &shareInfo) if err != nil { @@ -290,11 +299,41 @@ func (a *API) PublicPodFileDownload(pod *pod.ShareInfo, filePath string) (io.Rea return nil, 0, err } - fileInodeBytes, _, err := a.client.DownloadBlob(meta.InodeAddress) + r, _, err := a.client.DownloadBlob(swarm.NewAddress(meta.InodeAddress)) if err != nil { // skipcq: TCV-001 return nil, 0, err } + defer r.Close() + + fileInodeBytes, err := io.ReadAll(r) + 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 +} + +// PublicPodFileDownloadFromMetadata downloads a file from a public pod +func (a *API) PublicPodFileDownloadFromMetadata(meta *file.MetaData) (io.ReadCloser, uint64, error) { + + r, _, err := a.client.DownloadBlob(swarm.NewAddress(meta.InodeAddress)) + if err != nil { // skipcq: TCV-001 + return nil, 0, err + } + + defer r.Close() + + fileInodeBytes, err := io.ReadAll(r) + 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 @@ -335,7 +374,6 @@ func (a *API) PublicPodKVGetter(pod *pod.ShareInfo) KVGetter { // PublicPodDisLs lists a directory from a public pod 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) @@ -343,85 +381,455 @@ func (a *API) PublicPodDisLs(pod *pod.ShareInfo, dirPathToLs string) ([]dir.Entr fd := feed.New(accountInfo, a.client, a.feedCacheSize, a.feedCacheTTL, a.logger) dirNameWithPath := filepath.ToSlash(dirPathToLs) - topic := utils.HashString(dirNameWithPath) - _, data, err := fd.GetFeedData(topic, accountInfo.GetAddress(), []byte(pod.Password), false) + var ( + inode dir.Inode + data []byte + ) + + topic := utils.HashString(utils.CombinePathAndFile(dirNameWithPath, dir.IndexFileName)) + _, metaBytes, err := fd.GetFeedData(topic, accountInfo.GetAddress(), []byte(pod.Password), false) if err != nil { // skipcq: TCV-001 - if dirNameWithPath == utils.PathSeparator { - return nil, nil, nil + topic = utils.HashString(dirNameWithPath) + _, data, err = fd.GetFeedData(topic, accountInfo.GetAddress(), []byte(pod.Password), false) + if err != nil { + return nil, nil, fmt.Errorf("list dir : %v", err) // skipcq: TCV-001 + } + err = inode.Unmarshal(data) + if err != nil { // skipcq: TCV-001 + return nil, nil, err + } + } else { + if string(metaBytes) == utils.DeletedFeedMagicWord { + a.logger.Errorf("found deleted feed for %s\n", dirNameWithPath) + return nil, nil, file.ErrDeletedFeed + } + + var meta *file.MetaData + err = json.Unmarshal(metaBytes, &meta) + if err != nil { // skipcq: TCV-001 + return nil, nil, err + } + r, _, err := a.client.DownloadBlob(swarm.NewAddress(meta.InodeAddress)) + if err != nil { // skipcq: TCV-001 + return nil, nil, err + } + + defer r.Close() + + fileInodeBytes, err := io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + return nil, nil, err + } + var fileInode file.INode + err = json.Unmarshal(fileInodeBytes, &fileInode) + if err != nil { // skipcq: TCV-001 + return nil, nil, err + } + r = file.NewReader(fileInode, a.client, meta.Size, meta.BlockSize, meta.Compression, false) + data, err = io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + return nil, nil, err + } + err = inode.Unmarshal(data) + if err != nil { // skipcq: TCV-001 + return nil, nil, err } - 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) + var wg sync.WaitGroup + dirChan := make(chan dir.Entry, len(inode.FileOrDirNames)) + fileChan := make(chan file.Entry, len(inode.FileOrDirNames)) + errChan := make(chan error, len(inode.FileOrDirNames)) + semaphore := make(chan struct{}, 4) + missingCount := 0 + for _, fileOrDirName := range inode.FileOrDirNames { + wg.Add(1) + semaphore <- struct{}{} // Acquire a semaphore slot + + go func(fileOrDirName string) { + defer wg.Done() + defer func() { <-semaphore }() // Release the semaphore slot + if strings.HasPrefix(fileOrDirName, "_D_") { + + dirName := strings.TrimPrefix(fileOrDirName, "_D_") + dirPath := utils.CombinePathAndFile(dirNameWithPath, dirName) + var ( + inode dir.Inode + data []byte + ) + + dirTopic := utils.HashString(utils.CombinePathAndFile(dirPath, dir.IndexFileName)) + _, indexBytes, err := fd.GetFeedData(dirTopic, accountInfo.GetAddress(), []byte(pod.Password), false) + if err != nil { // skipcq: TCV-001 + topic = utils.HashString(dirName) + _, data, err = fd.GetFeedData(topic, accountInfo.GetAddress(), []byte(pod.Password), false) + if err != nil { + errChan <- fmt.Errorf("list dir : %v", err) + return + } + err = inode.Unmarshal(data) + if err != nil { + errChan <- err + return + } + } else { + if string(indexBytes) == utils.DeletedFeedMagicWord { + a.logger.Errorf("found deleted feed for %s\n", dirNameWithPath) + errChan <- file.ErrDeletedFeed + return + } + + var meta *file.MetaData + err = json.Unmarshal(indexBytes, &meta) + if err != nil { + errChan <- err + return + } + rOne, _, err := a.client.DownloadBlob(swarm.NewAddress(meta.InodeAddress)) + if err != nil { + errChan <- err + return + } + defer rOne.Close() + fileInodeBytes, err := io.ReadAll(rOne) + if err != nil { + errChan <- err + return + } + var fileInode file.INode + err = json.Unmarshal(fileInodeBytes, &fileInode) + if err != nil { + errChan <- err + return + } + rTwo := file.NewReader(fileInode, a.client, meta.Size, meta.BlockSize, meta.Compression, false) + defer rTwo.Close() + data, err = io.ReadAll(rTwo) + if err != nil { + errChan <- err + return + } + err = inode.Unmarshal(data) + if err != nil { + errChan <- err + return + } + } + entry := dir.Entry{ + Name: inode.Meta.Name, + ContentType: dir.MimeTypeDirectory, // per RFC2425 + CreationTime: strconv.FormatInt(inode.Meta.CreationTime, 10), + AccessTime: strconv.FormatInt(inode.Meta.AccessTime, 10), + ModificationTime: strconv.FormatInt(inode.Meta.ModificationTime, 10), + Mode: inode.Meta.Mode, + } + dirChan <- entry + } else if strings.HasPrefix(fileOrDirName, "_F_") { + fileName := strings.TrimPrefix(fileOrDirName, "_F_") + filePath := utils.CombinePathAndFile(dirNameWithPath, fileName) + + fileTopic := utils.HashString(utils.CombinePathAndFile(filePath, "")) + + _, data, err := fd.GetFeedData(fileTopic, accountInfo.GetAddress(), []byte(pod.Password), false) + if err != nil { // skipcq: TCV-001 + errChan <- fmt.Errorf("file mtdt : %s : %v", filePath, err) + return + } + if string(data) == utils.DeletedFeedMagicWord { // skipcq: TCV-001 + return + } + var meta *file.MetaData + err = json.Unmarshal(data, &meta) + if err != nil { // skipcq: TCV-001 + errChan <- fmt.Errorf("file mtdt : %v", err) + return + } + 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, + } + + fileChan <- entry + } + }(fileOrDirName) } + // Close channels in a goroutine after all goroutines are done + go func() { + wg.Wait() + close(dirChan) + close(fileChan) + close(errChan) + }() + var 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), false) - if err != nil { // skipcq: TCV-001 - return nil, nil, fmt.Errorf("list dir : %v", err) + var fileEntries []file.Entry + + for { + select { + case dirEntry, ok := <-dirChan: + if ok { + listEntries = append(listEntries, dirEntry) } - var dirInode *dir.Inode - err = json.Unmarshal(data, &dirInode) - if err != nil { // skipcq: TCV-001 - return nil, nil, fmt.Errorf("list dir : %v", err) + case fileEntry, ok := <-fileChan: + if ok { + fileEntries = append(fileEntries, fileEntry) } - entry := dir.Entry{ - Name: dirInode.Meta.Name, - ContentType: dir.MimeTypeDirectory, // 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, + case err := <-errChan: + if err != nil { + return nil, nil, err } - listEntries = append(listEntries, entry) - } else if strings.HasPrefix(fileOrDirName, "_F_") { - fileName := strings.TrimPrefix(fileOrDirName, "_F_") - filePath := utils.CombinePathAndFile(dirNameWithPath, fileName) - files = append(files, filePath) + case <-time.After(time.Hour): + return nil, nil, fmt.Errorf("timeout while listing directory") + } + if len(listEntries)+len(fileEntries)+missingCount == len(inode.FileOrDirNames) { + break } } - var fileEntries []file.Entry - for _, filePath := range files { - fileTopic := utils.HashString(utils.CombinePathAndFile(filePath, "")) + return listEntries, fileEntries, nil +} - _, data, err := fd.GetFeedData(fileTopic, accountInfo.GetAddress(), []byte(pod.Password), false) +// PublicPodSnapshot Gets the current snapshot from a public pod +func (a *API) PublicPodSnapshot(p *pod.ShareInfo, dirPathToLs string) (*pod.DirSnapShot, error) { + accountInfo := &account.Info{} + address := utils.HexToAddress(p.Address) + accountInfo.SetAddress(address) + dirSnapShot := &pod.DirSnapShot{ + FileList: make([]file.MetaData, 0), + DirList: make([]*pod.DirSnapShot, 0), + } + fd := feed.New(accountInfo, a.client, a.feedCacheSize, a.feedCacheTTL, a.logger) + + dirNameWithPath := filepath.ToSlash(dirPathToLs) + var ( + inode dir.Inode + data []byte + ) + fmt.Println("dirNameWithPath", dirNameWithPath) + + topic := utils.HashString(utils.CombinePathAndFile(dirNameWithPath, dir.IndexFileName)) + _, metaBytes, err := fd.GetFeedData(topic, accountInfo.GetAddress(), []byte(p.Password), false) + if err != nil { // skipcq: TCV-001 + fmt.Println("err", err) + topic = utils.HashString(dirNameWithPath) + _, data, err = fd.GetFeedData(topic, accountInfo.GetAddress(), []byte(p.Password), false) + if err != nil { + return nil, fmt.Errorf("list dir : %v for %s", err, dirNameWithPath) // skipcq: TCV-001 + } + err = inode.Unmarshal(data) if err != nil { // skipcq: TCV-001 - return nil, nil, fmt.Errorf("file mtdt : %v", err) + return nil, err } - if string(data) == utils.DeletedFeedMagicWord { // skipcq: TCV-001 - continue + } else { + if string(metaBytes) == utils.DeletedFeedMagicWord { + a.logger.Errorf("found deleted feed for %s\n", dirNameWithPath) + return nil, file.ErrDeletedFeed } + var meta *file.MetaData - err = json.Unmarshal(data, &meta) + err = json.Unmarshal(metaBytes, &meta) + if err != nil { // skipcq: TCV-001 + return nil, err + } + blobReader, _, err := a.client.DownloadBlob(swarm.NewAddress(meta.InodeAddress)) if err != nil { // skipcq: TCV-001 - return nil, nil, fmt.Errorf("file mtdt : %v", err) + return nil, 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, + + defer blobReader.Close() + + fileInodeBytes, err := io.ReadAll(blobReader) + if err != nil { // skipcq: TCV-001 + return nil, err } - fileEntries = append(fileEntries, entry) + var fileInode file.INode + err = json.Unmarshal(fileInodeBytes, &fileInode) + if err != nil { // skipcq: TCV-001 + return nil, err + } + r := file.NewReader(fileInode, a.client, meta.Size, meta.BlockSize, meta.Compression, false) + data, err = io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + return nil, err + } + err = inode.Unmarshal(data) + if err != nil { // skipcq: TCV-001 + return nil, err + } } + dirSnapShot.Name = inode.Meta.Name + dirSnapShot.ContentType = dir.MimeTypeDirectory + dirSnapShot.CreationTime = strconv.FormatInt(inode.Meta.CreationTime, 10) + dirSnapShot.AccessTime = strconv.FormatInt(inode.Meta.AccessTime, 10) + dirSnapShot.ModificationTime = strconv.FormatInt(inode.Meta.ModificationTime, 10) + dirSnapShot.Mode = inode.Meta.Mode + err = a.getSnapShotForDir(dirSnapShot, fd, accountInfo, inode.FileOrDirNames, dirNameWithPath, p.Password) + if err != nil { + return nil, err + } + return dirSnapShot, nil +} - return listEntries, fileEntries, nil +func (a *API) getSnapShotForDir(dirL *pod.DirSnapShot, fd *feed.API, accountInfo *account.Info, fileOrDirNames []string, dirNameWithPath, password string) error { + var wg sync.WaitGroup + dirChan := make(chan dir.Inode, len(fileOrDirNames)) + fileChan := make(chan file.MetaData, len(fileOrDirNames)) + errChan := make(chan error, len(fileOrDirNames)) + semaphore := make(chan struct{}, 4) + missingCount := 0 + for _, fileOrDirName := range fileOrDirNames { + wg.Add(1) + semaphore <- struct{}{} // Acquire a semaphore slot + + go func(fileOrDirName string) { + defer wg.Done() + defer func() { <-semaphore }() // Release the semaphore slot + if strings.HasPrefix(fileOrDirName, "_D_") { + + dirName := strings.TrimPrefix(fileOrDirName, "_D_") + dirPath := utils.CombinePathAndFile(dirNameWithPath, dirName) + var ( + inode dir.Inode + data []byte + ) + + dirTopic := utils.HashString(utils.CombinePathAndFile(dirPath, dir.IndexFileName)) + _, indexBytes, err := fd.GetFeedData(dirTopic, accountInfo.GetAddress(), []byte(password), false) + if err != nil { // skipcq: TCV-001 + topic := utils.HashString(dirName) + _, data, err = fd.GetFeedData(topic, accountInfo.GetAddress(), []byte(password), false) + if err != nil { + errChan <- fmt.Errorf("list dir : %v", err) + return + } + err = inode.Unmarshal(data) + if err != nil { + errChan <- err + return + } + } else { + if string(indexBytes) == utils.DeletedFeedMagicWord { + errChan <- file.ErrDeletedFeed + return + } + + var meta *file.MetaData + err = json.Unmarshal(indexBytes, &meta) + if err != nil { + errChan <- err + return + } + blobReader, _, err := a.client.DownloadBlob(swarm.NewAddress(meta.InodeAddress)) + if err != nil { + errChan <- err + return + } + + defer blobReader.Close() + + fileInodeBytes, err := io.ReadAll(blobReader) + if err != nil { + errChan <- err + return + } + var fileInode file.INode + err = json.Unmarshal(fileInodeBytes, &fileInode) + if err != nil { + errChan <- err + return + } + r := file.NewReader(fileInode, a.client, meta.Size, meta.BlockSize, meta.Compression, false) + data, err = io.ReadAll(r) + if err != nil { + errChan <- err + return + } + err = inode.Unmarshal(data) + if err != nil { + errChan <- err + return + } + } + dirChan <- inode + } else if strings.HasPrefix(fileOrDirName, "_F_") { + fileName := strings.TrimPrefix(fileOrDirName, "_F_") + filePath := utils.CombinePathAndFile(dirNameWithPath, fileName) + + fileTopic := utils.HashString(utils.CombinePathAndFile(filePath, "")) + + _, data, err := fd.GetFeedData(fileTopic, accountInfo.GetAddress(), []byte(password), false) + if err != nil { // skipcq: TCV-001 + errChan <- fmt.Errorf("file mtdt : %s : %v", filePath, err) + return + } + if string(data) == utils.DeletedFeedMagicWord { // skipcq: TCV-001 + return + } + var meta *file.MetaData + err = json.Unmarshal(data, &meta) + if err != nil { // skipcq: TCV-001 + errChan <- fmt.Errorf("file mtdt : %v", err) + return + } + + fileChan <- *meta + } + }(fileOrDirName) + } + + // Close channels in a goroutine after all goroutines are done + go func() { + wg.Wait() + close(dirChan) + close(fileChan) + close(errChan) + }() + + for { + select { + case inode, ok := <-dirChan: + if ok { + + dirItem := &pod.DirSnapShot{ + Name: inode.Meta.Name, + ContentType: dir.MimeTypeDirectory, + CreationTime: strconv.FormatInt(inode.Meta.CreationTime, 10), + AccessTime: strconv.FormatInt(inode.Meta.AccessTime, 10), + ModificationTime: strconv.FormatInt(inode.Meta.ModificationTime, 10), + Mode: inode.Meta.Mode, + DirList: make([]*pod.DirSnapShot, 0), + FileList: make([]file.MetaData, 0), + } + dirL.DirList = append(dirL.DirList, dirItem) + err := a.getSnapShotForDir(dirItem, fd, accountInfo, inode.FileOrDirNames, utils.CombinePathAndFile(dirNameWithPath, inode.Meta.Name), password) + if err != nil { + return err + } + } + case fileEntry, ok := <-fileChan: + if ok { + dirL.FileList = append(dirL.FileList, fileEntry) + } + case err := <-errChan: + if err != nil { + return err + } + case <-time.After(time.Hour): + return fmt.Errorf("timeout while listing directory") + } + if len(dirL.FileList)+len(dirL.DirList)+missingCount == len(fileOrDirNames) { + break + } + } + return nil } // PodReceive - receive a pod from a sharingReference diff --git a/pkg/dfs/user_api.go b/pkg/dfs/user_api.go index 37578cc2..2257f131 100644 --- a/pkg/dfs/user_api.go +++ b/pkg/dfs/user_api.go @@ -30,6 +30,11 @@ func (a *API) LoginUserV2(userName, passPhrase, sessionId string) (*user.LoginRe return a.users.LoginUserV2(userName, passPhrase, a.client, a.tm, a.sm, sessionId) } +// LoginUserWithSignature is a controller function which calls the users login with signature function. +func (a *API) LoginUserWithSignature(signature, passPhrase, sessionId string) (*user.LoginResponse, error) { + return a.users.LoginUserWithSignature(signature, 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, a.sm) diff --git a/pkg/dir/chmod_test.go b/pkg/dir/chmod_test.go index 5bfc2bae..1c2925da 100644 --- a/pkg/dir/chmod_test.go +++ b/pkg/dir/chmod_test.go @@ -7,14 +7,16 @@ import ( "testing" "time" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + "github.com/fairdatasociety/fairOS-dfs/pkg/file" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee/mock" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" "github.com/fairdatasociety/fairOS-dfs/pkg/dir" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -33,7 +35,8 @@ func TestChmod(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { @@ -54,7 +57,6 @@ func TestChmod(t *testing.T) { t.Run("chmod-dir", func(t *testing.T) { podPassword, _ := utils.GetRandString(pod.PasswordLength) dirObject := dir.NewDirectory("pod1", mockClient, fd, user, mockFile, tm, logger) - // make root dir so that other directories can be added err = dirObject.MkRootDir("pod1", podPassword, user, fd) if err != nil { diff --git a/pkg/dir/dir.go b/pkg/dir/dir.go index 2bae9937..c265649b 100644 --- a/pkg/dir/dir.go +++ b/pkg/dir/dir.go @@ -22,9 +22,9 @@ import ( "strconv" "sync" + blockstore "github.com/asabya/swarm-blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/taskmanager" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" f "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" diff --git a/pkg/dir/dir_present_test.go b/pkg/dir/dir_present_test.go index 7ed1e552..b6413406 100644 --- a/pkg/dir/dir_present_test.go +++ b/pkg/dir/dir_present_test.go @@ -18,18 +18,20 @@ package dir_test import ( "context" + "fmt" "io" "testing" "time" "github.com/fairdatasociety/fairOS-dfs/pkg/file" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee/mock" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" "github.com/fairdatasociety/fairOS-dfs/pkg/dir" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -48,7 +50,8 @@ func TestDirPresent(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/dir/dir_test.go b/pkg/dir/dir_test.go index 32c8576f..8883bde7 100644 --- a/pkg/dir/dir_test.go +++ b/pkg/dir/dir_test.go @@ -2,17 +2,19 @@ package dir_test import ( "context" + "fmt" "io" "testing" "time" "github.com/fairdatasociety/fairOS-dfs/pkg/file" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/dir" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -31,7 +33,8 @@ func TestDirRmAllFromMap(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/dir/inode.go b/pkg/dir/inode.go index d60d81cd..2707e9d8 100644 --- a/pkg/dir/inode.go +++ b/pkg/dir/inode.go @@ -73,7 +73,7 @@ func (d *Directory) GetInode(podPassword, dirNameWithPath string) (*Inode, error } var inode Inode var data []byte - r, _, err := d.file.Download(utils.CombinePathAndFile(dirNameWithPath, indexFileName), podPassword) + r, _, err := d.file.Download(utils.CombinePathAndFile(dirNameWithPath, IndexFileName), podPassword) if err != nil { // skipcq: TCV-001 topic := utils.HashString(dirNameWithPath) _, data, err = d.fd.GetFeedData(topic, d.getAddress(), []byte(podPassword), false) @@ -112,8 +112,7 @@ func (d *Directory) SetInode(podPassword string, iNode *Inode) error { if err != nil { // skipcq: TCV-001 return err } - - err = d.file.Upload(bufio.NewReader(bytes.NewBuffer(data)), indexFileName, int64(len(data)), file.MinBlockSize, 0, totalPath, "gzip", podPassword) + err = d.file.Upload(bufio.NewReader(bytes.NewBuffer(data)), IndexFileName, int64(len(data)), file.MinBlockSize, 0, totalPath, "gzip", podPassword) if err != nil { return err } @@ -131,7 +130,7 @@ func (d *Directory) RemoveInode(podPassword, dirNameWithPath string) error { } else { totalPath = utils.CombinePathAndFile(parentPath, dirToDelete) } - err := d.file.RmFile(utils.CombinePathAndFile(totalPath, indexFileName), podPassword) + err := d.file.RmFile(utils.CombinePathAndFile(totalPath, IndexFileName), podPassword) if err != nil { return err } diff --git a/pkg/dir/ls_test.go b/pkg/dir/ls_test.go index 02e2ed0c..3ff4cdcc 100644 --- a/pkg/dir/ls_test.go +++ b/pkg/dir/ls_test.go @@ -19,6 +19,7 @@ package dir_test import ( "context" "errors" + "fmt" "io" "sort" "testing" @@ -26,10 +27,11 @@ import ( "github.com/fairdatasociety/fairOS-dfs/pkg/file" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/sirupsen/logrus" @@ -52,7 +54,8 @@ func TestListDirectory(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/dir/mkdir_test.go b/pkg/dir/mkdir_test.go index 15a49f6d..5cfaf509 100644 --- a/pkg/dir/mkdir_test.go +++ b/pkg/dir/mkdir_test.go @@ -18,16 +18,18 @@ package dir_test import ( "context" + "fmt" "io" "testing" "time" "github.com/fairdatasociety/fairOS-dfs/pkg/file" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/sirupsen/logrus" @@ -49,7 +51,8 @@ func TestMkdir(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/dir/modify_dir_entry.go b/pkg/dir/modify_dir_entry.go index ebceb3b5..4dec4b7b 100644 --- a/pkg/dir/modify_dir_entry.go +++ b/pkg/dir/modify_dir_entry.go @@ -22,7 +22,7 @@ import ( ) const ( - indexFileName = "index.dfs" + IndexFileName = "index.dfs" ) // AddEntryToDir adds a new entry (directory/file) to a given directory. @@ -43,7 +43,6 @@ func (d *Directory) AddEntryToDir(parentDir, podPassword, itemToAdd string, isFi if err != nil { return ErrDirectoryNotPresent } - // add file or directory entry if isFile { itemToAdd = "_F_" + itemToAdd diff --git a/pkg/dir/rename.go b/pkg/dir/rename.go index d9b136dc..c4159f47 100644 --- a/pkg/dir/rename.go +++ b/pkg/dir/rename.go @@ -72,12 +72,12 @@ func (d *Directory) RenameDir(dirNameWithPath, newDirNameWithPath, podPassword s return err } - err = d.file.Upload(bufio.NewReader(strings.NewReader(string(fileMetaBytes))), indexFileName, int64(len(fileMetaBytes)), file.MinBlockSize, 0, newDirNameWithPath, "gzip", podPassword) + err = d.file.Upload(bufio.NewReader(strings.NewReader(string(fileMetaBytes))), IndexFileName, int64(len(fileMetaBytes)), file.MinBlockSize, 0, newDirNameWithPath, "gzip", podPassword) if err != nil { // skipcq: TCV-001 return err } - err = d.file.RmFile(utils.CombinePathAndFile(dirNameWithPath, indexFileName), podPassword) + err = d.file.RmFile(utils.CombinePathAndFile(dirNameWithPath, IndexFileName), podPassword) if err != nil { // skipcq: TCV-001 return err } diff --git a/pkg/dir/rename_test.go b/pkg/dir/rename_test.go index 0c732f86..fa6f2014 100644 --- a/pkg/dir/rename_test.go +++ b/pkg/dir/rename_test.go @@ -4,16 +4,18 @@ import ( "bytes" "context" "errors" + "fmt" "io" "sort" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/dir" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" @@ -33,7 +35,8 @@ func TestRenameDirectory(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/dir/rmdir.go b/pkg/dir/rmdir.go index 1918a5f7..6ca07012 100644 --- a/pkg/dir/rmdir.go +++ b/pkg/dir/rmdir.go @@ -52,7 +52,7 @@ func (d *Directory) RmDir(directoryNameWithPath, podPassword string) error { return ErrDirectoryNotPresent } - if dirInode.FileOrDirNames != nil && len(dirInode.FileOrDirNames) > 0 { + if len(dirInode.FileOrDirNames) > 0 { for _, fileOrDirName := range dirInode.FileOrDirNames { if strings.HasPrefix(fileOrDirName, "_F_") { fileName := strings.TrimPrefix(fileOrDirName, "_F_") @@ -93,7 +93,7 @@ func (d *Directory) RmRootDir(podPassword string) error { } // recursive delete dirInode := d.GetDirFromDirectoryMap(totalPath) - if dirInode.FileOrDirNames != nil && len(dirInode.FileOrDirNames) > 0 { + if len(dirInode.FileOrDirNames) > 0 { for _, fileOrDirName := range dirInode.FileOrDirNames { if strings.HasPrefix(fileOrDirName, "_F_") { fileName := strings.TrimPrefix(fileOrDirName, "_F_") diff --git a/pkg/dir/rmdir_test.go b/pkg/dir/rmdir_test.go index 5390ec34..68d87950 100644 --- a/pkg/dir/rmdir_test.go +++ b/pkg/dir/rmdir_test.go @@ -19,16 +19,18 @@ package dir_test import ( "context" "errors" + "fmt" "io" "testing" "time" "github.com/fairdatasociety/fairOS-dfs/pkg/file" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/sirupsen/logrus" @@ -50,7 +52,8 @@ func TestRmdir(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { @@ -187,7 +190,8 @@ func TestRmRootDirByPath(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { @@ -280,7 +284,8 @@ func TestRmRootDir(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/dir/stat_test.go b/pkg/dir/stat_test.go index 99a7d494..9e739fd1 100644 --- a/pkg/dir/stat_test.go +++ b/pkg/dir/stat_test.go @@ -19,17 +19,20 @@ package dir_test import ( "context" "errors" + "fmt" "io" "strconv" "testing" "time" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + "github.com/fairdatasociety/fairOS-dfs/pkg/file" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/sirupsen/logrus" @@ -51,7 +54,8 @@ func TestStat(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/dir/sync_test.go b/pkg/dir/sync_test.go index 07561b51..b7327588 100644 --- a/pkg/dir/sync_test.go +++ b/pkg/dir/sync_test.go @@ -18,6 +18,7 @@ package dir_test import ( "context" + "fmt" "io" "sync" "testing" @@ -25,11 +26,12 @@ import ( "github.com/fairdatasociety/fairOS-dfs/pkg/file" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/dir" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -53,7 +55,8 @@ func TestSync(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/ensm/eth/eth.go b/pkg/ensm/eth/eth.go index d1ab0535..9d5306c9 100644 --- a/pkg/ensm/eth/eth.go +++ b/pkg/ensm/eth/eth.go @@ -8,7 +8,7 @@ import ( "math/big" "time" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" diff --git a/pkg/ensm/eth/mock/eth.go b/pkg/ensm/eth/mock/eth.go index 69795ace..a4a2f1ee 100644 --- a/pkg/ensm/eth/mock/eth.go +++ b/pkg/ensm/eth/mock/eth.go @@ -9,7 +9,7 @@ import ( "github.com/fairdatasociety/fairOS-dfs/pkg/utils" goens "github.com/wealdtech/go-ens/v3" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/ethereum/go-ethereum/common" ) diff --git a/pkg/feed/api.go b/pkg/feed/api.go index 3584106b..615aab11 100644 --- a/pkg/feed/api.go +++ b/pkg/feed/api.go @@ -21,11 +21,11 @@ import ( "fmt" "time" - "github.com/ethersphere/bee/pkg/crypto" - "github.com/ethersphere/bee/pkg/swarm" + blockstore "github.com/asabya/swarm-blockstore" + "github.com/ethersphere/bee/v2/pkg/crypto" + "github.com/ethersphere/bee/v2/pkg/swarm" bmtlegacy "github.com/ethersphere/bmt/legacy" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/feed/lookup" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" @@ -174,11 +174,11 @@ func (a *API) CreateFeedFromTopic(topic []byte, user utils.Address, data []byte) func (a *API) GetSOCFromAddress(address []byte) ([]byte, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - data, err := a.handler.client.DownloadChunk(ctx, address) + ch, err := a.handler.client.DownloadChunk(ctx, swarm.NewAddress(address)) if err != nil { return nil, err } - ch := swarm.NewChunk(swarm.NewAddress(address), data) + return a.handler.rawSignedChunkData(ch) } diff --git a/pkg/feed/feed_test.go b/pkg/feed/feed_test.go index e64db33b..b0ddb52a 100644 --- a/pkg/feed/feed_test.go +++ b/pkg/feed/feed_test.go @@ -20,17 +20,19 @@ import ( "bytes" "crypto/rand" "errors" + "fmt" "io" "testing" "time" "github.com/stretchr/testify/require" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "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/utils" @@ -49,7 +51,7 @@ func TestFeed(t *testing.T) { Storer: storer, Post: mockpost.New(mockpost.WithAcceptAll()), }) - client := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + client := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) t.Run("create-feed", func(t *testing.T) { acc := account.New(logger) diff --git a/pkg/feed/handler.go b/pkg/feed/handler.go index 006ad272..3479bdab 100644 --- a/pkg/feed/handler.go +++ b/pkg/feed/handler.go @@ -24,21 +24,20 @@ import ( "encoding/hex" "errors" "fmt" - "github.com/fairdatasociety/fairOS-dfs/pkg/logging" "hash" "strings" "sync" "sync/atomic" "time" - bCrypto "github.com/ethersphere/bee/pkg/crypto" - "github.com/ethersphere/bee/pkg/soc" - "github.com/ethersphere/bee/pkg/swarm" + blockstore "github.com/asabya/swarm-blockstore" + bCrypto "github.com/ethersphere/bee/v2/pkg/crypto" + "github.com/ethersphere/bee/v2/pkg/soc" + "github.com/ethersphere/bee/v2/pkg/swarm" bmtlegacy "github.com/ethersphere/bmt/legacy" - utilsSigner "github.com/fairdatasociety/fairOS-dfs-utils/signer" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/feed/lookup" + "github.com/fairdatasociety/fairOS-dfs/pkg/logging" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/hashicorp/golang-lru/v2/expirable" "golang.org/x/crypto/sha3" @@ -304,15 +303,15 @@ retry: func (h *Handler) update(id, owner, signature, data []byte) ([]byte, error) { // send the SOC chunk - addr, err := h.client.UploadSOC(utils.Encode(owner), utils.Encode(id), utils.Encode(signature), data) + addr, err := h.client.UploadSOC(utils.Encode(owner), utils.Encode(id), utils.Encode(signature), "", "0", false, data) if err != nil { return nil, err } - return addr, nil + return addr.Bytes(), nil } func (h *Handler) deleteChunk(ref []byte) error { - return h.client.DeleteReference(ref) + return h.client.DeleteReference(swarm.NewAddress(ref)) } // GetContent retrieves the data payload of the last synced update of the feed @@ -373,14 +372,13 @@ func (h *Handler) Lookup(ctx context.Context, query *Query) (*CacheEntry, error) if err != nil { // skipcq: TCV-001 return nil, err } - data, err := h.client.DownloadChunk(ctx, addr.Bytes()) + ch, err := h.client.DownloadChunk(ctx, addr) if err != nil { if errors.Is(err, context.DeadlineExceeded) || err.Error() == "error downloading data" { // chunk not found return nil, nil } return nil, err } - ch := swarm.NewChunk(addr, data) var request request if err := h.fromChunk(ch, &request, query, &id); err != nil { @@ -423,11 +421,10 @@ func (h *Handler) LookupEpoch(ctx context.Context, query *Query) (*CacheEntry, e if err != nil { // skipcq: TCV-001 return nil, err } - data, err := h.client.DownloadChunk(ctx, addr.Bytes()) + ch, err := h.client.DownloadChunk(ctx, addr) if err != nil { return nil, err } - ch := swarm.NewChunk(addr, data) var request request if err := h.fromChunk(ch, &request, query, &id); err != nil { return nil, err @@ -615,7 +612,7 @@ func (h *Handler) getSignature(id, payloadId []byte) ([]byte, []byte, error) { if err != nil { return nil, nil, err } - signer := utilsSigner.NewDefaultSigner(h.accountInfo.GetPrivateKey()) + signer := bCrypto.NewDefaultSigner(h.accountInfo.GetPrivateKey()) signature, err := signer.Sign(toSignBytes) if err != nil { return nil, nil, err diff --git a/pkg/feed/handler_test.go b/pkg/feed/handler_test.go index a22c2b98..88e08c1e 100644 --- a/pkg/feed/handler_test.go +++ b/pkg/feed/handler_test.go @@ -1,16 +1,19 @@ package feed import ( + "fmt" "io" "testing" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/ethersphere/bee/pkg/swarm" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/swarm" bmtlegacy "github.com/ethersphere/bmt/legacy" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" ) @@ -22,7 +25,7 @@ func TestHandler(t *testing.T) { Storer: storer, Post: mockpost.New(mockpost.WithAcceptAll()), }) - client := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + client := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) t.Run("new-handler", func(t *testing.T) { acc := account.New(logger) diff --git a/pkg/feed/tracker/tracker.go b/pkg/feed/tracker/tracker.go index e17c4d18..641d089b 100644 --- a/pkg/feed/tracker/tracker.go +++ b/pkg/feed/tracker/tracker.go @@ -10,7 +10,7 @@ package tracker // "strings" // "sync" // -// "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" +// "github.com/asabya/swarm-blockstore" // "github.com/fairdatasociety/fairOS-dfs/pkg/feed" // "github.com/fairdatasociety/fairOS-dfs/pkg/logging" // "github.com/fairdatasociety/fairOS-dfs/pkg/utils" diff --git a/pkg/feed/tracker/tracker_test.go b/pkg/feed/tracker/tracker_test.go index 68acfec3..523c21f8 100644 --- a/pkg/feed/tracker/tracker_test.go +++ b/pkg/feed/tracker/tracker_test.go @@ -10,7 +10,7 @@ package tracker // "github.com/stretchr/testify/require" // // "github.com/fairdatasociety/fairOS-dfs/pkg/account" -// "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" +// "github.com/asabya/swarm-blockstore/bee/mock" // "github.com/fairdatasociety/fairOS-dfs/pkg/feed" // "github.com/fairdatasociety/fairOS-dfs/pkg/feed/lookup" // "github.com/fairdatasociety/fairOS-dfs/pkg/logging" diff --git a/pkg/file/chmod_test.go b/pkg/file/chmod_test.go index 0b9458c8..12f6760e 100644 --- a/pkg/file/chmod_test.go +++ b/pkg/file/chmod_test.go @@ -7,11 +7,12 @@ import ( "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -32,7 +33,8 @@ func TestChmod(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/file/download.go b/pkg/file/download.go index dd644ec8..b4419419 100644 --- a/pkg/file/download.go +++ b/pkg/file/download.go @@ -21,6 +21,8 @@ import ( "errors" "io" + "github.com/ethersphere/bee/v2/pkg/swarm" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" ) @@ -55,7 +57,14 @@ func (f *File) ReadSeeker(podFileWithPath, podPassword string) (io.ReadSeekClose if meta == nil { // skipcq: TCV-001 return nil, 0, ErrFileNotFound } - fileInodeBytes, _, err := f.getClient().DownloadBlob(meta.InodeAddress) + r, _, err := f.getClient().DownloadBlob(swarm.NewAddress(meta.InodeAddress)) + if err != nil { // skipcq: TCV-001 + return nil, 0, err + } + + defer r.Close() + + fileInodeBytes, err := io.ReadAll(r) if err != nil { // skipcq: TCV-001 return nil, 0, err } diff --git a/pkg/file/download_test.go b/pkg/file/download_test.go index f1bf2359..5abef00e 100644 --- a/pkg/file/download_test.go +++ b/pkg/file/download_test.go @@ -24,11 +24,12 @@ import ( "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -49,7 +50,8 @@ func TestDownload(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") require.NoError(t, err) diff --git a/pkg/file/file.go b/pkg/file/file.go index 254a511b..fa8a2741 100644 --- a/pkg/file/file.go +++ b/pkg/file/file.go @@ -25,7 +25,7 @@ import ( "github.com/fairdatasociety/fairOS-dfs/pkg/taskmanager" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" + blockstore "github.com/asabya/swarm-blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" diff --git a/pkg/file/ls_test.go b/pkg/file/ls_test.go index 40a3c132..9bf35cde 100644 --- a/pkg/file/ls_test.go +++ b/pkg/file/ls_test.go @@ -24,11 +24,12 @@ import ( "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -47,7 +48,8 @@ func TestListFiles(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/file/meta.go b/pkg/file/meta.go index 6dd8569e..2c14d858 100644 --- a/pkg/file/meta.go +++ b/pkg/file/meta.go @@ -73,7 +73,8 @@ func (f *File) handleMeta(meta *MetaData, podPassword string) error { if err == nil || errors.Is(err, ErrDeletedFeed) { return f.updateMeta(meta, podPassword) } - return f.uploadMeta(meta, podPassword) + err = f.uploadMeta(meta, podPassword) + return err } func (f *File) uploadMeta(meta *MetaData, podPassword string) error { diff --git a/pkg/file/reader.go b/pkg/file/reader.go index a0a1214a..edc7686d 100644 --- a/pkg/file/reader.go +++ b/pkg/file/reader.go @@ -20,9 +20,10 @@ import ( "bytes" "encoding/json" "errors" + "github.com/ethersphere/bee/v2/pkg/swarm" "io" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" + blockstore "github.com/asabya/swarm-blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/golang/snappy" lru "github.com/hashicorp/golang-lru/v2/expirable" @@ -66,11 +67,17 @@ func (f *File) OpenFileForIndex(podFile, podPassword string) (*Reader, error) { return nil, ErrFileNotFound } - encryptedFileInodeBytes, _, err := f.getClient().DownloadBlob(meta.InodeAddress) + r, _, err := f.getClient().DownloadBlob(swarm.NewAddress(meta.InodeAddress)) if err != nil { return nil, err } + defer r.Close() + + encryptedFileInodeBytes, err := io.ReadAll(r) + if err != nil { + return nil, err + } temp := make([]byte, len(encryptedFileInodeBytes)) copy(temp, encryptedFileInodeBytes) fileInodeBytes, err := utils.DecryptBytes([]byte(podPassword), temp) @@ -313,11 +320,16 @@ func (r *Reader) getBlock(ref []byte, compression string, blockSize uint32) ([]b return data, nil } } - stdoutBytes, _, err := r.client.DownloadBlob(ref) + rd, _, err := r.client.DownloadBlob(swarm.NewAddress(ref)) if err != nil { // skipcq: TCV-001 return nil, err } + defer rd.Close() + stdoutBytes, err := io.ReadAll(rd) + if err != nil { // skipcq: TCV-001 + return nil, err + } decompressedData, err := Decompress(stdoutBytes, compression, blockSize) if err != nil { // skipcq: TCV-001 return nil, err diff --git a/pkg/file/reader_test.go b/pkg/file/reader_test.go index 0140f212..54a38047 100644 --- a/pkg/file/reader_test.go +++ b/pkg/file/reader_test.go @@ -17,19 +17,19 @@ limitations under the License. package file_test import ( + "bytes" "crypto/rand" "errors" + "fmt" "io" "math/big" "testing" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/logging" - "github.com/sirupsen/logrus" - - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/stretchr/testify/assert" @@ -44,8 +44,7 @@ func TestFileReader(t *testing.T) { Post: mockpost.New(mockpost.WithAcceptAll()), }) - logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) t.Run("read-entire-file-shorter-than-block", func(t *testing.T) { fileSize := uint64(15) @@ -343,14 +342,14 @@ func createFile(t *testing.T, fileSize uint64, blockSize uint32, compression str buf = compressedData } - addr, err := mockClient.UploadBlob(buf, 0, true) + addr, err := mockClient.UploadBlob(0, "", "0", false, true, bytes.NewReader(buf)) if err != nil { t.Fatal(err) } fileBlock := &file.BlockInfo{ Size: bytesToWrite, CompressedSize: uint32(len(buf)), - Reference: utils.NewReference(addr), + Reference: utils.NewReference(addr.Bytes()), } fileBlocks = append(fileBlocks, fileBlock) bytesRemaining -= uint64(bytesToWrite) @@ -467,14 +466,14 @@ func createFileWithNewlines(t *testing.T, fileSize uint64, blockSize uint32, com buf = compressedData } - addr, err := mockClient.UploadBlob(buf, 0, true) + addr, err := mockClient.UploadBlob(0, "", "0", false, true, bytes.NewReader(buf)) if err != nil { t.Fatal(err) } fileBlock := &file.BlockInfo{ Size: bytesToWrite, CompressedSize: uint32(len(buf)), - Reference: utils.NewReference(addr), + Reference: utils.NewReference(addr.Bytes()), } fileBlocks = append(fileBlocks, fileBlock) bytesRemaining -= uint64(bytesToWrite) diff --git a/pkg/file/rename_test.go b/pkg/file/rename_test.go index edd2d330..5ce0b817 100644 --- a/pkg/file/rename_test.go +++ b/pkg/file/rename_test.go @@ -3,15 +3,17 @@ package file_test import ( "bytes" "context" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/dir" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" @@ -31,7 +33,8 @@ func TestRename(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/file/rm.go b/pkg/file/rm.go index 3e83a9ed..31c479ff 100644 --- a/pkg/file/rm.go +++ b/pkg/file/rm.go @@ -19,9 +19,10 @@ package file import ( "encoding/json" "fmt" + "io" "net/http" - "github.com/ethersphere/bee/pkg/swarm" + "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" ) @@ -32,7 +33,7 @@ func (f *File) RmFile(podFileWithPath, podPassword string) error { if meta == nil { return ErrFileNotFound } - fileInodeBytes, respCode, err := f.client.DownloadBlob(meta.InodeAddress) + r, respCode, err := f.client.DownloadBlob(swarm.NewAddress(meta.InodeAddress)) if err != nil { // skipcq: TCV-001 return err } @@ -40,7 +41,13 @@ func (f *File) RmFile(podFileWithPath, podPassword string) error { f.logger.Warningf("could not remove blocks in %s", swarm.NewAddress(meta.InodeAddress).String()) return fmt.Errorf("could not remove blocks in %v", swarm.NewAddress(meta.InodeAddress).String()) } + defer r.Close() + fileInodeBytes, err := io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + f.logger.Warningf("could not read data in address %s", swarm.NewAddress(meta.InodeAddress).String()) + return fmt.Errorf("could not read data in address %v", swarm.NewAddress(meta.InodeAddress).String()) + } // find the inode and remove the blocks present in the inode one by one var fInode *INode err = json.Unmarshal(fileInodeBytes, &fInode) @@ -49,13 +56,13 @@ func (f *File) RmFile(podFileWithPath, podPassword string) error { return fmt.Errorf("could not unmarshall data in address %v", swarm.NewAddress(meta.InodeAddress).String()) } - err = f.client.DeleteReference(meta.InodeAddress) + err = f.client.DeleteReference(swarm.NewAddress(meta.InodeAddress)) if err != nil { f.logger.Errorf("could not delete file inode %s", swarm.NewAddress(meta.InodeAddress).String()) return fmt.Errorf("could not delete file inode %s: %s", swarm.NewAddress(meta.InodeAddress).String(), err.Error()) } for _, fblocks := range fInode.Blocks { - err = f.client.DeleteReference(fblocks.Reference.Bytes()) + err = f.client.DeleteReference(swarm.NewAddress(fblocks.Reference.Bytes())) if err != nil { // skipcq: TCV-001 f.logger.Errorf("could not delete file block %s", swarm.NewAddress(fblocks.Reference.Bytes()).String()) return fmt.Errorf("could not delete file inode %v", swarm.NewAddress(fblocks.Reference.Bytes()).String()) diff --git a/pkg/file/rm_test.go b/pkg/file/rm_test.go index 26f28334..0e49fa12 100644 --- a/pkg/file/rm_test.go +++ b/pkg/file/rm_test.go @@ -18,15 +18,17 @@ package file_test import ( "context" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -46,7 +48,8 @@ func TestRemoveFile(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") require.NoError(t, err) diff --git a/pkg/file/stat_test.go b/pkg/file/stat_test.go index dee6f886..b4bfe616 100644 --- a/pkg/file/stat_test.go +++ b/pkg/file/stat_test.go @@ -24,11 +24,13 @@ import ( "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -47,7 +49,8 @@ func TestStat(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/file/status_test.go b/pkg/file/status_test.go index bae2680c..da27ce5d 100644 --- a/pkg/file/status_test.go +++ b/pkg/file/status_test.go @@ -2,17 +2,20 @@ package file_test import ( "context" + "fmt" "io" "testing" "time" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + "github.com/stretchr/testify/require" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -31,7 +34,8 @@ func TestStatus(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/file/upload.go b/pkg/file/upload.go index 5c07ebdc..cbf49648 100644 --- a/pkg/file/upload.go +++ b/pkg/file/upload.go @@ -28,6 +28,8 @@ import ( "sync" "time" + "github.com/ethersphere/bee/v2/pkg/swarm" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/golang/snappy" "github.com/klauspost/pgzip" @@ -58,8 +60,7 @@ func (f *File) Upload(fd io.Reader, podFileName string, fileSize int64, blockSiz } reader := bufio.NewReader(fd) now := time.Now().Unix() - - tag, err := f.client.CreateTag(nil) + tag, err := f.client.CreateTag(swarm.ZeroAddress) if err != nil { // skipcq: TCV-001 return err } @@ -146,8 +147,7 @@ func (f *File) Upload(fd io.Reader, podFileName string, fileSize int64, blockSiz return } } - - addr, uploadErr := f.client.UploadBlob(uploadData, tag, true) + addr, uploadErr := f.client.UploadBlob(tag, "", "0", false, true, bytes.NewReader(uploadData)) if uploadErr != nil { mainErr = uploadErr return @@ -156,7 +156,7 @@ func (f *File) Upload(fd io.Reader, podFileName string, fileSize int64, blockSiz fileBlock := &BlockInfo{ Size: uint32(size), CompressedSize: uint32(len(uploadData)), - Reference: utils.NewReference(addr), + Reference: utils.NewReference(addr.Bytes()), } refMapMu.Lock() @@ -186,23 +186,19 @@ func (f *File) Upload(fd io.Reader, podFileName string, fileSize int64, blockSiz for i := 0; i < len(refMap); i++ { fileINode.Blocks = append(fileINode.Blocks, refMap[i]) } - fileInodeData, err := json.Marshal(fileINode) if err != nil { // skipcq: TCV-001 return err } - - addr, err := f.client.UploadBlob(fileInodeData, 0, true) + addr, err := f.client.UploadBlob(tag, "", "0", false, true, bytes.NewReader(fileInodeData)) if err != nil { // skipcq: TCV-001 return err } - - meta.InodeAddress = addr + meta.InodeAddress = addr.Bytes() err = f.handleMeta(&meta, podPassword) if err != nil { // skipcq: TCV-001 return err } - totalPath := utils.CombinePathAndFile(meta.Path, meta.Name) f.AddToFileMap(totalPath, &meta) if tag > 0 { diff --git a/pkg/file/upload_test.go b/pkg/file/upload_test.go index ed3cdea6..9aaea8bc 100644 --- a/pkg/file/upload_test.go +++ b/pkg/file/upload_test.go @@ -21,17 +21,19 @@ import ( "context" "crypto/rand" "errors" + "fmt" "io" "os" "path/filepath" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -50,7 +52,8 @@ func TestUpload(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/file/writeAt.go b/pkg/file/writeAt.go index 00350d24..09ea3f99 100644 --- a/pkg/file/writeAt.go +++ b/pkg/file/writeAt.go @@ -8,6 +8,8 @@ import ( "io" "sync" + "github.com/ethersphere/bee/v2/pkg/swarm" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" ) @@ -26,7 +28,14 @@ func (f *File) WriteAt(podFileWithPath, podPassword string, update io.Reader, of } // download file inode (blocks info) - fileInodeBytes, _, err := f.getClient().DownloadBlob(meta.InodeAddress) + r, _, err := f.getClient().DownloadBlob(swarm.NewAddress(meta.InodeAddress)) + if err != nil { // skipcq: TCV-001 + return 0, err + } + + defer r.Close() + + fileInodeBytes, err := io.ReadAll(r) if err != nil { // skipcq: TCV-001 return 0, err } @@ -204,7 +213,7 @@ func (f *File) WriteAt(podFileWithPath, podPassword string, update io.Reader, of } } - addr, uploadErr := f.client.UploadBlob(uploadData, tag, true) + addr, uploadErr := f.client.UploadBlob(tag, "", "0", false, true, bytes.NewReader(uploadData)) if uploadErr != nil { mainErr = uploadErr return @@ -213,7 +222,7 @@ func (f *File) WriteAt(podFileWithPath, podPassword string, update io.Reader, of fileBlock := &BlockInfo{ Size: uint32(size), CompressedSize: uint32(len(uploadData)), - Reference: utils.NewReference(addr), + Reference: utils.NewReference(addr.Bytes()), } refMapMu.Lock() @@ -249,11 +258,11 @@ func (f *File) WriteAt(podFileWithPath, podPassword string, update io.Reader, of return 0, err } - addr, err := f.client.UploadBlob(fileInodeData, 0, true) + addr, err := f.client.UploadBlob(tag, "", "0", false, true, bytes.NewReader(fileInodeData)) if err != nil { // skipcq: TCV-001 return 0, err } - meta.InodeAddress = addr + meta.InodeAddress = addr.Bytes() meta.Size = newDataSize err = f.handleMeta(meta, podPassword) diff --git a/pkg/file/writeAt_test.go b/pkg/file/writeAt_test.go index 64a0baa8..8ea52e05 100644 --- a/pkg/file/writeAt_test.go +++ b/pkg/file/writeAt_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "errors" + "fmt" "io" "math/rand" "os" @@ -11,11 +12,13 @@ import ( "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -40,7 +43,8 @@ func TestWriteAt(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/pod/fork.go b/pkg/pod/fork.go index 9348f12d..acaca56a 100644 --- a/pkg/pod/fork.go +++ b/pkg/pod/fork.go @@ -3,9 +3,12 @@ package pod import ( "encoding/json" "fmt" + "io" "net/http" "strings" + "github.com/ethersphere/bee/v2/pkg/swarm" + d "github.com/fairdatasociety/fairOS-dfs/pkg/dir" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" f "github.com/fairdatasociety/fairOS-dfs/pkg/file" @@ -48,13 +51,19 @@ func (p *Pod) PodForkFromRef(forkName, refString string) error { if err != nil { return nil } - data, resp, err := p.client.DownloadBlob(ref.Bytes()) + r, resp, err := p.client.DownloadBlob(swarm.NewAddress(ref.Bytes())) if err != nil { // skipcq: TCV-001 return err } if resp != http.StatusOK { // skipcq: TCV-001 return fmt.Errorf("ReceivePod: could not download blob") } + defer r.Close() + data, err := io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + return err + } + var shareInfo ShareInfo err = json.Unmarshal(data, &shareInfo) if err != nil { // skipcq: TCV-001 diff --git a/pkg/pod/group.go b/pkg/pod/group.go index cc51780d..4e51044d 100644 --- a/pkg/pod/group.go +++ b/pkg/pod/group.go @@ -11,12 +11,12 @@ import ( "strings" "sync" + blockstore "github.com/asabya/swarm-blockstore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/fairdatasociety/fairOS-dfs/pkg/account" "github.com/fairdatasociety/fairOS-dfs/pkg/acl" aclController "github.com/fairdatasociety/fairOS-dfs/pkg/acl/acl" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" c "github.com/fairdatasociety/fairOS-dfs/pkg/collection" d "github.com/fairdatasociety/fairOS-dfs/pkg/dir" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" diff --git a/pkg/pod/groupMember.go b/pkg/pod/groupMember.go index b3924ca2..f41a80e7 100644 --- a/pkg/pod/groupMember.go +++ b/pkg/pod/groupMember.go @@ -1,12 +1,16 @@ package pod import ( + "bytes" "crypto/ecdsa" "crypto/sha256" "encoding/json" "errors" + "io" "strings" + "github.com/ethersphere/bee/v2/pkg/swarm" + aclController "github.com/fairdatasociety/fairOS-dfs/pkg/acl/acl" "github.com/ethereum/go-ethereum/crypto" @@ -71,7 +75,7 @@ func (g *Group) AddMember(groupName string, memberAddress common.Address, member return nil, err } - ref, err := g.client.UploadBlob(data, 0, false) + ref, err := g.client.UploadBlob(0, "", "0", false, false, bytes.NewReader(data)) if err != nil { return nil, err } @@ -81,7 +85,7 @@ func (g *Group) AddMember(groupName string, memberAddress common.Address, member return nil, err } - return ref, nil + return ref.Bytes(), nil } func (g *Group) AcceptGroupInvite(ref []byte) error { @@ -91,10 +95,18 @@ func (g *Group) AcceptGroupInvite(ref []byte) error { } // download blob - data, _, err := g.client.DownloadBlob(ref) + r, _, err := g.client.DownloadBlob(swarm.NewAddress(ref)) if err != nil { return err } + + defer r.Close() + + data, err := io.ReadAll(r) + if err != nil { + return err + } + // unmarshall into GroupItem group := &GroupItem{} err = json.Unmarshal(data, group) diff --git a/pkg/pod/ls.go b/pkg/pod/ls.go index 3531d5c9..4e97f42f 100644 --- a/pkg/pod/ls.go +++ b/pkg/pod/ls.go @@ -26,9 +26,11 @@ func (p *Pod) ListPods() ([]string, []string, error) { if err != nil { // skipcq: TCV-001 return nil, nil, err } - err := p.storeUserPodsV2(podList) - if err != nil { - fmt.Println("error storing podsV2", err) + if len(podList.Pods) != 0 || len(podList.SharedPods) != 0 { + err := p.storeUserPodsV2(podList) + if err != nil { + fmt.Println("error storing podsV2", err) + } } } diff --git a/pkg/pod/new.go b/pkg/pod/new.go index bd9995a3..26bd0aec 100644 --- a/pkg/pod/new.go +++ b/pkg/pod/new.go @@ -211,7 +211,6 @@ func (p *Pod) loadUserPodsV2() (*List, error) { } func (p *Pod) storeUserPodsV2(podList *List) error { - data, err := json.Marshal(podList) if err != nil { return err diff --git a/pkg/pod/open.go b/pkg/pod/open.go index c83cee87..f59fe000 100644 --- a/pkg/pod/open.go +++ b/pkg/pod/open.go @@ -122,7 +122,7 @@ func (p *Pod) OpenPod(podName string) (*Info, error) { return podInfo, nil } -func (p *Pod) OpenFromShareInfo(si *ShareInfo) (*Info, error) { +func (p *Pod) OpenActPod(si *ShareInfo, actName string) (*Info, error) { accountInfo := p.acc.GetEmptyAccountInfo() address := utils.HexToAddress(si.Address) accountInfo.SetAddress(address) @@ -145,13 +145,35 @@ func (p *Pod) OpenFromShareInfo(si *ShareInfo) (*Info, error) { kvStore: kvStore, docStore: docStore, } - p.addPodToPodMap(si.PodName, podInfo) + p.addPodToPodMap(actName, podInfo) - // sync the pod's files and directories - err := p.SyncPod(si.PodName) - if err != nil && err != d.ErrResourceDeleted { // skipcq: TCV-001 - 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.feedCacheSize, p.feedCacheTTL, 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) return podInfo, nil } diff --git a/pkg/pod/pod.go b/pkg/pod/pod.go index 1eb69813..abd83614 100644 --- a/pkg/pod/pod.go +++ b/pkg/pod/pod.go @@ -21,12 +21,12 @@ import ( "sync" "time" - "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager" - + blockstore "github.com/asabya/swarm-blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" + "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" + "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager" "github.com/fairdatasociety/fairOS-dfs/pkg/taskmanager" ) @@ -71,6 +71,19 @@ type List struct { SharedPods []SharedListItem `json:"sharedPods"` } +type DirSnapShot struct { + Name string `json:"name"` + ContentType string `json:"contentType"` + Size string `json:"size,omitempty"` + Mode uint32 `json:"mode"` + BlockSize string `json:"blockSize,omitempty"` + CreationTime string `json:"creationTime"` + ModificationTime string `json:"modificationTime"` + AccessTime string `json:"accessTime"` + FileList []file.MetaData `json:"fileList"` + DirList []*DirSnapShot `json:"dirList"` +} + // 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, sm subscriptionManager.SubscriptionManager, feedCacheSize int, feedCacheTTL time.Duration, logger logging.Logger) *Pod { return &Pod{ diff --git a/pkg/pod/sharing.go b/pkg/pod/sharing.go index ca8bc40a..658bd39c 100644 --- a/pkg/pod/sharing.go +++ b/pkg/pod/sharing.go @@ -17,10 +17,14 @@ limitations under the License. package pod import ( + "bytes" "encoding/json" "fmt" + "io" "net/http" + "github.com/ethersphere/bee/v2/pkg/swarm" + "github.com/fairdatasociety/fairOS-dfs/pkg/utils" ) @@ -72,13 +76,12 @@ func (p *Pod) PodShare(podName, sharedPodName string) (string, error) { if err != nil { // skipcq: TCV-001 return "", err } - ref, err := p.client.UploadBlob(data, 0, false) + ref, err := p.client.UploadBlob(0, "", "0", false, false, bytes.NewReader(data)) if err != nil { // skipcq: TCV-001 return "", err } - shareInfoRef := utils.NewReference(ref) - return shareInfoRef.String(), nil + return ref.String(), nil } // GetPodSharingInfo returns the raw shareInfo @@ -116,7 +119,7 @@ func (p *Pod) GetPodSharingInfo(podName string) (*ShareInfo, error) { // ReceivePodInfo returns the shareInfo from the reference func (p *Pod) ReceivePodInfo(ref utils.Reference) (*ShareInfo, error) { - data, resp, err := p.client.DownloadBlob(ref.Bytes()) + r, resp, err := p.client.DownloadBlob(swarm.NewAddress(ref.Bytes())) if err != nil { // skipcq: TCV-001 return nil, err } @@ -124,7 +127,12 @@ func (p *Pod) ReceivePodInfo(ref utils.Reference) (*ShareInfo, error) { if resp != http.StatusOK { // skipcq: TCV-001 return nil, fmt.Errorf("ReceivePodInfo: could not download blob") } + defer r.Close() + data, err := io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + return nil, err + } var shareInfo ShareInfo err = json.Unmarshal(data, &shareInfo) if err != nil { @@ -136,13 +144,19 @@ func (p *Pod) ReceivePodInfo(ref utils.Reference) (*ShareInfo, error) { // ReceivePod imports a pod by creating a new pod with the same name and password func (p *Pod) ReceivePod(sharedPodName string, ref utils.Reference) (*Info, error) { - data, resp, err := p.client.DownloadBlob(ref.Bytes()) + r, resp, err := p.client.DownloadBlob(swarm.NewAddress(ref.Bytes())) if err != nil { // skipcq: TCV-001 return nil, err } if resp != http.StatusOK { // skipcq: TCV-001 return nil, fmt.Errorf("receivePod: could not download blob") } + defer r.Close() + + data, err := io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + return nil, err + } var shareInfo ShareInfo err = json.Unmarshal(data, &shareInfo) if err != nil { // skipcq: TCV-001 diff --git a/pkg/pod/subscription.go b/pkg/pod/subscription.go index 013ed418..f719b5b6 100644 --- a/pkg/pod/subscription.go +++ b/pkg/pod/subscription.go @@ -1,13 +1,16 @@ package pod import ( + "bytes" "crypto/ecdsa" "crypto/sha256" - "encoding/hex" "encoding/json" "fmt" + "io" "net/http" + "github.com/ethersphere/bee/v2/pkg/swarm" + "github.com/ethereum/go-ethereum/common" "github.com/fairdatasociety/fairOS-dfs/pkg/contracts/datahub" "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc" @@ -91,12 +94,12 @@ func (p *Pod) EncryptUploadSubscriptionInfo(podName string, subscriberPublicKey return "", err } - ref, err := p.client.UploadBlob(encData, 0, false) + ref, err := p.client.UploadBlob(0, "", "0", false, false, bytes.NewReader(encData)) if err != nil { return "", err } - return hex.EncodeToString(ref), nil + return ref.String(), nil } // RequestSubscription will send a subscriptionManager request to the owner of the pod @@ -145,11 +148,11 @@ func (p *Pod) OpenSubscribedPodFromReference(reference string, ownerPublicKey *e a, _ := ownerPublicKey.Curve.ScalarMult(ownerPublicKey.X, ownerPublicKey.Y, p.acc.GetUserAccountInfo().GetPrivateKey().D.Bytes()) secret := sha256.Sum256(a.Bytes()) - ref, err := hex.DecodeString(reference) + ref, err := swarm.ParseHexAddress(reference) if err != nil { // skipcq: TCV-001 return nil, err } - encData, resp, err := p.client.DownloadBlob(ref) + r, resp, err := p.client.DownloadBlob(ref) if err != nil { // skipcq: TCV-001 return nil, err } @@ -157,7 +160,12 @@ func (p *Pod) OpenSubscribedPodFromReference(reference string, ownerPublicKey *e if resp != http.StatusOK { // skipcq: TCV-001 return nil, fmt.Errorf("OpenSubscribedPodFromReference: could not get subscription info") } + defer r.Close() + encData, err := io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + return nil, err + } data, err := utils.DecryptBytes(secret[:], encData) if err != nil { return nil, err diff --git a/pkg/subscriptionManager/rpc/manager.go b/pkg/subscriptionManager/rpc/manager.go index dff4e548..63dbcbe7 100644 --- a/pkg/subscriptionManager/rpc/manager.go +++ b/pkg/subscriptionManager/rpc/manager.go @@ -1,15 +1,19 @@ package rpc import ( + "bytes" "context" "crypto/ecdsa" "encoding/json" "errors" "fmt" + "io" "math/big" "net/http" "time" + "github.com/ethersphere/bee/v2/pkg/swarm" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -30,13 +34,13 @@ const ( ) type SubscriptionInfoPutter interface { - UploadBlob(data []byte, tag uint32, encrypt bool) (address []byte, err error) - UploadBzz(data []byte, fileName string) (address []byte, err error) + UploadBlob(tag uint32, stamp, redundancyLevel string, pin, encrypt bool, data io.Reader) (address swarm.Address, err error) + UploadFileBzz(data []byte, fileName, stamp, redundancyLevel string, pin bool) (address swarm.Address, err error) } type SubscriptionInfoGetter interface { - DownloadBlob(address []byte) (data []byte, respCode int, err error) - DownloadBzz(address []byte) (data []byte, respCode int, err error) + DownloadBlob(address swarm.Address) (reader io.ReadCloser, respCode int, err error) + DownloadBzz(address swarm.Address) (data []byte, respCode int, err error) } type SubscriptionItemInfo struct { @@ -87,12 +91,12 @@ func (c *Client) AddPodToMarketplace(podAddress, owner common.Address, pod, titl if err != nil { // skipcq: TCV-001 return err } - ref, err := c.putter.UploadBzz(data, fmt.Sprintf("%d.sub.json", time.Now().Unix())) + ref, err := c.putter.UploadFileBzz(data, fmt.Sprintf("%d.sub.json", time.Now().Unix()), "", "0", false) if err != nil { // skipcq: TCV-001 return err } var a [32]byte - copy(a[:], ref) + copy(a[:], ref.Bytes()) tx, err := c.datahub.ListSub(opts, nameHash, a, new(big.Int).SetUint64(price), category, podAddress, new(big.Int).SetUint64(uint64(daysValid))) if err != nil { @@ -166,13 +170,13 @@ func (c *Client) AllowAccess(owner common.Address, shareInfo *ShareInfo, request return err } - ref, err := c.putter.UploadBlob(encData, 0, false) + ref, err := c.putter.UploadBlob(0, "", "0", false, false, bytes.NewReader(encData)) if err != nil { return err } var fixedRef [32]byte - copy(fixedRef[:], ref) + copy(fixedRef[:], ref.Bytes()) tx, err := c.datahub.SellSub(opts, requestHash, fixedRef) if err != nil { @@ -188,13 +192,19 @@ func (c *Client) AllowAccess(owner common.Address, shareInfo *ShareInfo, request } func (c *Client) GetSubscription(infoLocation []byte, secret [32]byte) (*ShareInfo, error) { - encData, respCode, err := c.getter.DownloadBlob(infoLocation) + r, respCode, err := c.getter.DownloadBlob(swarm.NewAddress(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") } + defer r.Close() + + encData, err := io.ReadAll(r) + if err != nil { // skipcq: TCV-001 + return nil, err + } data, err := utils.DecryptBytes(secret[:], encData) if err != nil { @@ -215,7 +225,7 @@ func (c *Client) GetSubscribablePodInfo(subHash [32]byte) (*SubscriptionItemInfo if err != nil { return nil, err } - data, respCode, err := c.getter.DownloadBzz(item.SwarmLocation[:]) + data, respCode, err := c.getter.DownloadBzz(swarm.NewAddress(item.SwarmLocation[:])) if err != nil { // skipcq: TCV-001 return nil, err } diff --git a/pkg/test/close_test.go b/pkg/test/close_test.go index 568f7558..3534e294 100644 --- a/pkg/test/close_test.go +++ b/pkg/test/close_test.go @@ -18,15 +18,17 @@ package test_test import ( "context" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "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" @@ -45,7 +47,8 @@ func TestClose(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/test/del_test.go b/pkg/test/del_test.go index 6972c89f..5a3e9fc2 100644 --- a/pkg/test/del_test.go +++ b/pkg/test/del_test.go @@ -18,17 +18,19 @@ package test_test import ( "context" + "fmt" "io" "sort" "strings" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/collection" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -48,7 +50,8 @@ func TestPodDelete(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") diff --git a/pkg/test/delete_test.go b/pkg/test/delete_test.go index f4b3b20a..a02f0cdf 100644 --- a/pkg/test/delete_test.go +++ b/pkg/test/delete_test.go @@ -19,14 +19,16 @@ package test_test import ( "context" "errors" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/ensm/eth/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" @@ -44,7 +46,8 @@ func TestDelete(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + tm := taskmanager.New(1, 10, time.Second*15, logger) defer func() { _ = tm.Stop(context.Background()) diff --git a/pkg/test/fork_test.go b/pkg/test/fork_test.go index 3a35f20a..13506905 100644 --- a/pkg/test/fork_test.go +++ b/pkg/test/fork_test.go @@ -18,15 +18,17 @@ package test_test import ( "context" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -46,7 +48,8 @@ func TestFork(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/test/group_new_test.go b/pkg/test/group_new_test.go index 70230234..376af62d 100644 --- a/pkg/test/group_new_test.go +++ b/pkg/test/group_new_test.go @@ -22,13 +22,15 @@ import ( "io" "testing" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/ethereum/go-ethereum/common" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" "github.com/fairdatasociety/fairOS-dfs/pkg/acl/acl" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -46,7 +48,8 @@ func TestGroupNew(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { @@ -155,7 +158,6 @@ func TestGroupNew(t *testing.T) { mockAcl := acl.NewACL(mockClient, fd, logger) group := pod.NewGroup(mockClient, fd, acc, mockAcl, logger) groupName1, _ := utils.GetRandString(10) - fmt.Println("group name", groupName1) _, err = group.CreateGroup(groupName1) if err != nil { t.Fatalf("error creating group %s: %s", groupName1, err.Error()) @@ -263,7 +265,6 @@ func TestGroupNew(t *testing.T) { if err != nil { t.Fatal(err) } - fmt.Println("permission", perm) if perm != acl.PermissionWrite { t.Fatal("permission does not match") } diff --git a/pkg/test/integration_test.go b/pkg/test/integration_test.go index 22d23b27..fdf4af98 100644 --- a/pkg/test/integration_test.go +++ b/pkg/test/integration_test.go @@ -2,20 +2,22 @@ package test_test import ( "crypto/rand" + "fmt" "io" "math/big" "path/filepath" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/asabya/swarm-blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/file" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/cmd/common" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/dfs" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/ensm/eth/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -47,7 +49,7 @@ func TestLiteUser(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) users := user.NewUsers(mockClient, ens, -1, 0, logger) dfsApi := dfs.NewMockDfsAPI(mockClient, users, logger) diff --git a/pkg/test/lite_test.go b/pkg/test/lite_test.go index f52b396e..a5b656a3 100644 --- a/pkg/test/lite_test.go +++ b/pkg/test/lite_test.go @@ -3,14 +3,17 @@ package test_test import ( "context" "errors" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/ensm/eth/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" @@ -28,7 +31,8 @@ func TestLite(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + tm := taskmanager.New(1, 10, time.Second*15, logger) defer func() { _ = tm.Stop(context.Background()) diff --git a/pkg/test/login_test.go b/pkg/test/login_test.go index fd09d672..d23e8080 100644 --- a/pkg/test/login_test.go +++ b/pkg/test/login_test.go @@ -19,19 +19,21 @@ package test_test import ( "context" "errors" + "fmt" "io" "sort" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" "github.com/sirupsen/logrus" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-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/pod" @@ -49,7 +51,8 @@ func TestLogin(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + tm := taskmanager.New(1, 10, time.Second*15, logger) defer func() { _ = tm.Stop(context.Background()) diff --git a/pkg/test/logout_test.go b/pkg/test/logout_test.go index 582f04d0..63732962 100644 --- a/pkg/test/logout_test.go +++ b/pkg/test/logout_test.go @@ -19,20 +19,22 @@ package test_test import ( "context" "errors" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" "github.com/sirupsen/logrus" "github.com/plexsysio/taskmanager" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-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" @@ -47,7 +49,8 @@ func TestLogout(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + tm := taskmanager.New(1, 10, time.Second*15, logger) defer func() { _ = tm.Stop(context.Background()) diff --git a/pkg/test/ls_test.go b/pkg/test/ls_test.go index 3baf02b8..3dae128c 100644 --- a/pkg/test/ls_test.go +++ b/pkg/test/ls_test.go @@ -18,13 +18,15 @@ package test_test import ( "context" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/asabya/swarm-blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/sirupsen/logrus" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" @@ -35,8 +37,8 @@ import ( "github.com/plexsysio/taskmanager" + "github.com/asabya/swarm-blockstore/bee/mock" "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" ) @@ -50,7 +52,8 @@ func TestPod_ListPods(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) accountInfo := acc.GetUserAccountInfo() fd := feed.New(accountInfo, mockClient, -1, 0, logger) diff --git a/pkg/test/max_file_test.go b/pkg/test/max_file_test.go index fadf883b..c03f3ca7 100644 --- a/pkg/test/max_file_test.go +++ b/pkg/test/max_file_test.go @@ -2,23 +2,25 @@ package test_test import ( "context" + "fmt" "io" "testing" "time" "github.com/fairdatasociety/fairOS-dfs/pkg/file" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" "github.com/sirupsen/logrus" "github.com/plexsysio/taskmanager" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "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" @@ -34,7 +36,8 @@ func TestMaxFiles(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/test/max_pod_test.go b/pkg/test/max_pod_test.go index f2a1379a..a436348b 100644 --- a/pkg/test/max_pod_test.go +++ b/pkg/test/max_pod_test.go @@ -2,23 +2,25 @@ package test_test import ( "context" + "fmt" "io" "testing" "time" "github.com/stretchr/testify/require" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" "github.com/sirupsen/logrus" "github.com/plexsysio/taskmanager" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "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" @@ -34,7 +36,8 @@ func TestMaxPods(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/test/new_test.go b/pkg/test/new_test.go index d779e84b..8b7150bc 100644 --- a/pkg/test/new_test.go +++ b/pkg/test/new_test.go @@ -19,20 +19,22 @@ package test_test import ( "context" "errors" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" "github.com/sirupsen/logrus" "github.com/plexsysio/taskmanager" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-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" @@ -47,7 +49,8 @@ func TestNew(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + tm := taskmanager.New(1, 10, time.Second*15, logger) defer func() { _ = tm.Stop(context.Background()) diff --git a/pkg/test/open_test.go b/pkg/test/open_test.go index 8e1ab00c..e6a84124 100644 --- a/pkg/test/open_test.go +++ b/pkg/test/open_test.go @@ -20,14 +20,16 @@ import ( "context" "crypto/rand" "errors" + "fmt" "io" "os" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/asabya/swarm-blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/sirupsen/logrus" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" @@ -36,8 +38,8 @@ import ( "github.com/plexsysio/taskmanager" + "github.com/asabya/swarm-blockstore/bee/mock" "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/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" @@ -53,7 +55,8 @@ func TestOpen(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/test/pod_new_test.go b/pkg/test/pod_new_test.go index 1f8a417d..9fa270ec 100644 --- a/pkg/test/pod_new_test.go +++ b/pkg/test/pod_new_test.go @@ -19,14 +19,16 @@ package test_test import ( "context" "errors" + "fmt" "io" "strings" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/asabya/swarm-blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/sirupsen/logrus" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" @@ -35,8 +37,8 @@ import ( "github.com/fairdatasociety/fairOS-dfs/pkg/utils" + "github.com/asabya/swarm-blockstore/bee/mock" "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" @@ -51,7 +53,8 @@ func TestPodNew(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/test/pod_sharing_test.go b/pkg/test/pod_sharing_test.go index 373d841b..546464e5 100644 --- a/pkg/test/pod_sharing_test.go +++ b/pkg/test/pod_sharing_test.go @@ -19,12 +19,14 @@ package test_test import ( "context" "errors" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/sirupsen/logrus" @@ -33,9 +35,9 @@ import ( "github.com/plexsysio/taskmanager" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "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" @@ -51,7 +53,8 @@ func TestShare(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/test/pod_stat_test.go b/pkg/test/pod_stat_test.go index 2a361f73..2aa1358b 100644 --- a/pkg/test/pod_stat_test.go +++ b/pkg/test/pod_stat_test.go @@ -18,13 +18,15 @@ package test_test import ( "context" + "fmt" "io" "strings" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" "github.com/sirupsen/logrus" @@ -33,9 +35,9 @@ import ( "github.com/plexsysio/taskmanager" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "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" @@ -50,7 +52,8 @@ func TestStat(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/test/stat_test.go b/pkg/test/stat_test.go index e868ed7f..48eb5e18 100644 --- a/pkg/test/stat_test.go +++ b/pkg/test/stat_test.go @@ -19,12 +19,14 @@ package test_test import ( "context" "errors" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" "github.com/sirupsen/logrus" @@ -33,8 +35,8 @@ import ( "github.com/plexsysio/taskmanager" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/ensm/eth/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" ) @@ -48,7 +50,8 @@ func TestUserStat(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + tm := taskmanager.New(1, 10, time.Second*15, logger) defer func() { _ = tm.Stop(context.Background()) diff --git a/pkg/test/subscription_test.go b/pkg/test/subscription_test.go index 3f1e5747..195d7a32 100644 --- a/pkg/test/subscription_test.go +++ b/pkg/test/subscription_test.go @@ -11,16 +11,17 @@ import ( "github.com/ethereum/go-ethereum/crypto" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/asabya/swarm-blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/sirupsen/logrus" "github.com/fairdatasociety/fairOS-dfs/pkg/file" + "github.com/asabya/swarm-blockstore/bee/mock" "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" @@ -40,7 +41,8 @@ func TestSubscription(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc1 := account.New(logger) _, _, err := acc1.CreateUserAccount("") if err != nil { @@ -148,7 +150,10 @@ func TestSubscription(t *testing.T) { dirObject := pi.GetDirectory() - dirInode1 := dirObject.GetDirFromDirectoryMap("/parentDir/subDir1") + dirInode1, err := dirObject.GetInode(pi.GetPodPassword(), "/parentDir/subDir1") + if err != nil { + t.Fatal(err) + } if dirInode1 == nil { t.Fatalf("invalid dir entry") } @@ -159,10 +164,11 @@ func TestSubscription(t *testing.T) { if dirInode1.Meta.Name != "subDir1" { t.Fatalf("invalid dir entry") } - dirInode2 := dirObject.GetDirFromDirectoryMap("/parentDir/subDir2") - if dirInode2 == nil { - t.Fatalf("invalid dir entry") + dirInode2, err := dirObject.GetInode(pi.GetPodPassword(), "/parentDir/subDir2") + if err != nil { + t.Fatal(err) } + if dirInode2.Meta.Path != "/parentDir" { t.Fatalf("invalid path entry") } diff --git a/pkg/test/sync_test.go b/pkg/test/sync_test.go index 9802d25c..ea5563a5 100644 --- a/pkg/test/sync_test.go +++ b/pkg/test/sync_test.go @@ -18,21 +18,24 @@ package test_test import ( "context" + "fmt" "io" "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/sirupsen/logrus" mock2 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/asabya/swarm-blockstore/bee" + "github.com/asabya/swarm-blockstore/bee/mock" "github.com/fairdatasociety/fairOS-dfs/pkg/account" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" - "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" @@ -49,7 +52,8 @@ func TestSync(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) + acc := account.New(logger) _, _, err := acc.CreateUserAccount("") if err != nil { diff --git a/pkg/test/user_sharing_test.go b/pkg/test/user_sharing_test.go index 09e7455d..0e8790e4 100644 --- a/pkg/test/user_sharing_test.go +++ b/pkg/test/user_sharing_test.go @@ -25,15 +25,16 @@ import ( "testing" "time" - mockpost "github.com/ethersphere/bee/pkg/postage/mock" - mockstorer "github.com/ethersphere/bee/pkg/storer/mock" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore/bee" + "github.com/asabya/swarm-blockstore/bee" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/sirupsen/logrus" mock3 "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager/rpc/mock" + "github.com/asabya/swarm-blockstore/bee/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" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" "github.com/fairdatasociety/fairOS-dfs/pkg/file" @@ -53,7 +54,7 @@ func TestSharing(t *testing.T) { }) logger := logging.New(io.Discard, logrus.DebugLevel) - mockClient := bee.NewBeeClient(beeUrl, mock.BatchOkStr, true, logger) + mockClient := bee.NewBeeClient(beeUrl, bee.WithStamp(mock.BatchOkStr), bee.WithRedundancy(fmt.Sprintf("%d", redundancy.NONE)), bee.WithPinning(true)) acc1 := account.New(logger) _, _, err := acc1.CreateUserAccount("") diff --git a/pkg/user/info.go b/pkg/user/info.go index e2db8b35..ffa14663 100644 --- a/pkg/user/info.go +++ b/pkg/user/info.go @@ -19,6 +19,8 @@ package user import ( "sync" + "github.com/fairdatasociety/fairOS-dfs/pkg/act" + "github.com/fairdatasociety/fairOS-dfs/pkg/account" d "github.com/fairdatasociety/fairOS-dfs/pkg/dir" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" @@ -38,6 +40,7 @@ type Info struct { group *pod.Group openPods map[string]*pod.Info openPodsMu *sync.RWMutex + actList *act.ACT } // GetUserName return username @@ -55,6 +58,10 @@ func (i *Info) GetPod() *pod.Pod { return i.pod } +func (i *Info) GetACTList() *act.ACT { + return i.actList +} + // GetGroup returns user group handler func (i *Info) GetGroup() *pod.Group { return i.group diff --git a/pkg/user/login.go b/pkg/user/login.go index 59584136..c444eb33 100644 --- a/pkg/user/login.go +++ b/pkg/user/login.go @@ -17,9 +17,14 @@ limitations under the License. package user import ( + "crypto/ecdsa" + "encoding/hex" "fmt" "sync" + "github.com/fairdatasociety/fairOS-dfs/pkg/act" + + blockstore "github.com/asabya/swarm-blockstore" acl2 "github.com/fairdatasociety/fairOS-dfs/pkg/acl/acl" "github.com/ethereum/go-ethereum/common" @@ -27,7 +32,6 @@ import ( "github.com/fairdatasociety/fairOS-dfs/pkg/account" "github.com/fairdatasociety/fairOS-dfs/pkg/auth" "github.com/fairdatasociety/fairOS-dfs/pkg/auth/jwt" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" d "github.com/fairdatasociety/fairOS-dfs/pkg/dir" "github.com/fairdatasociety/fairOS-dfs/pkg/feed" f "github.com/fairdatasociety/fairOS-dfs/pkg/file" @@ -75,7 +79,7 @@ func (u *Users) LoginUserV2(userName, passPhrase string, client blockstore.Clien } // load public key from public resolver - publicKey, nameHash, err := u.ens.GetInfo(userName) + publicKey, nameHash, err := u.GetUserInfo(userName) if err != nil { // skipcq: TCV-001 return nil, err } @@ -95,11 +99,15 @@ 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, sm, u.feedCacheSize, u.feedCacheTTL, u.logger) - acl := acl2.NewACL(u.client, fd, u.logger) - group := p.NewGroup(u.client, fd, acc, acl, u.logger) - dir := d.NewDirectory(userName, client, fd, accountInfo.GetAddress(), file, tm, u.logger) + var ( + file = f.NewFile(userName, client, fd, accountInfo.GetAddress(), tm, u.logger) + pod = p.NewPod(u.client, fd, acc, tm, sm, u.feedCacheSize, u.feedCacheTTL, u.logger) + acl = acl2.NewACL(u.client, fd, u.logger) + group = p.NewGroup(u.client, fd, acc, acl, u.logger) + dir = d.NewDirectory(userName, client, fd, accountInfo.GetAddress(), file, tm, u.logger) + actList = act.NewACT(client, fd, acc, tm, u.logger) + ) + if sessionId == "" { sessionId = auth.GetUniqueSessionId() } @@ -115,6 +123,7 @@ func (u *Users) LoginUserV2(userName, passPhrase string, client blockstore.Clien group: group, openPods: make(map[string]*p.Info), openPodsMu: &sync.RWMutex{}, + actList: actList, } // set cookie and add user to map if err = u.addUserAndSessionToMap(ui); err != nil { // skipcq: TCV-001 @@ -129,7 +138,69 @@ func (u *Users) LoginUserV2(userName, passPhrase string, client blockstore.Clien return &LoginResponse{ Address: address.Hex(), NameHash: nameHash, - PublicKey: utils.Encode(crypto.FromECDSAPub(publicKey)), + PublicKey: hex.EncodeToString(crypto.FromECDSAPub(publicKey)), + UserInfo: ui, + AccessToken: token, + }, nil +} + +// LoginUserWithSignature logs an user with a provided signature +func (u *Users) LoginUserWithSignature(signature, password string, client blockstore.Client, tm taskmanager.TaskManagerGO, sm subscriptionManager.SubscriptionManager, sessionId string) (*LoginResponse, error) { + // check if sessionId is still active + if u.IsUserLoggedIn(sessionId) { // skipcq: TCV-001 + return nil, ErrUserAlreadyLoggedIn + } + + // create account + acc := account.New(u.logger) + accountInfo := acc.GetUserAccountInfo() + // load encrypted private key + fd := feed.New(accountInfo, client, u.feedCacheSize, u.feedCacheTTL, u.logger) + + _, _, err := acc.GenerateUserAccountFromSignature(signature, password) + if err != nil { // skipcq: TCV-001 + return nil, err + } + addr := accountInfo.GetAddress() + // Instantiate pod, dir & file objects + file := f.NewFile(addr.String(), u.client, fd, addr, tm, u.logger) + dir := d.NewDirectory(addr.String(), u.client, fd, addr, file, tm, u.logger) + pod := p.NewPod(u.client, fd, acc, tm, sm, u.feedCacheSize, u.feedCacheTTL, u.logger) + acl := acl2.NewACL(u.client, fd, u.logger) + group := p.NewGroup(u.client, fd, acc, acl, u.logger) + actList := act.NewACT(client, fd, acc, tm, u.logger) + if sessionId == "" { + sessionId = auth.GetUniqueSessionId() + } + + ui := &Info{ + name: addr.String(), + sessionId: sessionId, + feedApi: fd, + account: acc, + file: file, + dir: dir, + pod: pod, + group: group, + openPods: make(map[string]*p.Info), + openPodsMu: &sync.RWMutex{}, + actList: actList, + } + + // set cookie and add user to map + err = u.addUserAndSessionToMap(ui) + if err != nil { + return nil, err + } + + token, err := jwt.GenerateToken(sessionId) + if err != nil { + u.logger.Errorf("error generating token: %v\n", err) + } + + return &LoginResponse{ + Address: addr.Hex(), + PublicKey: hex.EncodeToString(crypto.FromECDSAPub(accountInfo.GetPublicKey())), UserInfo: ui, AccessToken: token, }, nil @@ -260,6 +331,7 @@ func (u *Users) LoginWithWallet(addressHex, signature string, client blockstore. acl := acl2.NewACL(u.client, fd, u.logger) group := p.NewGroup(u.client, fd, acc, acl, u.logger) dir := d.NewDirectory(addressHex, client, fd, accountInfo.GetAddress(), file, tm, u.logger) + actList := act.NewACT(client, fd, acc, tm, u.logger) if sessionId == "" { sessionId = auth.GetUniqueSessionId() } @@ -274,7 +346,12 @@ func (u *Users) LoginWithWallet(addressHex, signature string, client blockstore. group: group, openPods: make(map[string]*p.Info), openPodsMu: &sync.RWMutex{}, + actList: actList, } // set cookie and add user to map return ui, utils.Encode(nameHash[:]), u.addUserAndSessionToMap(ui) } + +func (u *Users) GetUserInfo(userName string) (*ecdsa.PublicKey, string, error) { + return u.ens.GetInfo(userName) +} diff --git a/pkg/user/new.go b/pkg/user/new.go index 9da77f2d..eeb600b9 100644 --- a/pkg/user/new.go +++ b/pkg/user/new.go @@ -17,10 +17,15 @@ limitations under the License. package user import ( + "encoding/hex" "errors" "regexp" "sync" + "github.com/fairdatasociety/fairOS-dfs/pkg/act" + + "github.com/fairdatasociety/fairOS-dfs/pkg/auth/jwt" + acl2 "github.com/fairdatasociety/fairOS-dfs/pkg/acl/acl" "github.com/ethereum/go-ethereum/common" @@ -34,7 +39,6 @@ import ( p "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/fairdatasociety/fairOS-dfs/pkg/subscriptionManager" "github.com/fairdatasociety/fairOS-dfs/pkg/taskmanager" - "github.com/fairdatasociety/fairOS-dfs/pkg/utils" ) const ( @@ -44,11 +48,12 @@ const ( // SignupResponse is the response of a successful signup type SignupResponse struct { - Address string `json:"address"` - Mnemonic string `json:"mnemonic"` - NameHash string `json:"nameHash"` - PublicKey string `json:"publicKey"` - UserInfo *Info `json:"userInfo"` + Address string `json:"address"` + Mnemonic string `json:"mnemonic"` + NameHash string `json:"nameHash"` + PublicKey string `json:"publicKey"` + UserInfo *Info `json:"userInfo"` + AccessToken string `json:"accessToken"` } // CreateNewUserV2 creates a new user with the given username and password. if a mnemonic is passed @@ -130,6 +135,7 @@ func (u *Users) CreateNewUserV2(userName, passPhrase, mnemonic, sessionId string pod := p.NewPod(u.client, fd, acc, tm, sm, u.feedCacheSize, u.feedCacheTTL, u.logger) acl := acl2.NewACL(u.client, fd, u.logger) group := p.NewGroup(u.client, fd, acc, acl, u.logger) + actList := act.NewACT(u.client, fd, acc, tm, u.logger) if sessionId == "" { sessionId = auth.GetUniqueSessionId() } @@ -145,14 +151,22 @@ func (u *Users) CreateNewUserV2(userName, passPhrase, mnemonic, sessionId string group: group, openPods: make(map[string]*p.Info), openPodsMu: &sync.RWMutex{}, + actList: actList, } // set cookie and add user to map if err = u.addUserAndSessionToMap(ui); err != nil { // skipcq: TCV-001 return nil, err } + + token, err := jwt.GenerateToken(sessionId) + if err != nil { + u.logger.Errorf("error generating token: %v\n", err) + } + signUp.UserInfo = ui - signUp.PublicKey = utils.Encode(crypto.FromECDSAPub(accountInfo.GetPublicKey())) + signUp.PublicKey = hex.EncodeToString(crypto.FromECDSAPub(accountInfo.GetPublicKey())) + signUp.AccessToken = token return signUp, nil } diff --git a/pkg/user/sharing.go b/pkg/user/sharing.go index 13b45b26..dd5f79fc 100644 --- a/pkg/user/sharing.go +++ b/pkg/user/sharing.go @@ -17,12 +17,15 @@ limitations under the License. package user import ( - "encoding/hex" + "bytes" "encoding/json" + "io" "net/http" "strconv" "time" + "github.com/ethersphere/bee/v2/pkg/swarm" + f "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/pod" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" @@ -89,26 +92,31 @@ func (u *Users) ShareFileWithUser(podName, podPassword, podFileWithPath, destina } // upload the encrypted data and get the reference - ref, err := u.client.UploadBlob(data, 0, true) + ref, err := u.client.UploadBlob(0, "", "0", false, true, bytes.NewReader(data)) if err != nil { // skipcq: TCV-001 return "", err } - return hex.EncodeToString(ref), nil + return ref.String(), nil } // ReceiveFileFromUser imports an exported file in to the current user and pod by reading the sharing file entry. func (u *Users) ReceiveFileFromUser(_ *Info, pd *pod.Pod, podName, ref, podDir string) (string, error) { - refBytes, err := hex.DecodeString(ref) + refBytes, err := swarm.ParseHexAddress(ref) if err != nil { return "", err } // get the encrypted meta - data, respCode, err := u.client.DownloadBlob(refBytes) + r, respCode, err := u.client.DownloadBlob(refBytes) if err != nil || respCode != http.StatusOK { return "", err } // skipcq: TCV-001 + defer r.Close() + data, err := io.ReadAll(r) + if err != nil { + return "", err + } // unmarshall the entry sharingEntry := SharingEntry{} err = json.Unmarshal(data, &sharingEntry) @@ -163,28 +171,39 @@ func (u *Users) ReceiveFileFromUser(_ *Info, pd *pod.Pod, podName, ref, podDir s // ReceiveFileInfo displays the information of the exported file. This is used to decide whether // to import the file or not. func (u *Users) ReceiveFileInfo(ref string) (*ReceiveFileInfo, error) { - refBytes, err := hex.DecodeString(ref) + refBytes, err := swarm.ParseHexAddress(ref) if err != nil { return nil, err } // get the encrypted meta - data, respCode, err := u.client.DownloadBlob(refBytes) + r, respCode, err := u.client.DownloadBlob(refBytes) if err != nil || respCode != http.StatusOK { // skipcq: TCV-001 return nil, err } + defer r.Close() + data, err := io.ReadAll(r) + if err != nil { + return nil, err + } // unmarshall the entry sharingEntry := SharingEntry{} err = json.Unmarshal(data, &sharingEntry) if err != nil { // skipcq: TCV-001 return nil, err } - fileInodeBytes, respCode, err := u.client.DownloadBlob(sharingEntry.Meta.InodeAddress) + inodeReader, respCode, err := u.client.DownloadBlob(swarm.NewAddress(sharingEntry.Meta.InodeAddress)) if err != nil || respCode != http.StatusOK { // skipcq: TCV-001 return nil, err } + defer inodeReader.Close() + + fileInodeBytes, err := io.ReadAll(inodeReader) + if err != nil { + return nil, err + } var fileInode f.INode err = json.Unmarshal(fileInodeBytes, &fileInode) if err != nil { // skipcq: TCV-001 diff --git a/pkg/user/users.go b/pkg/user/users.go index 98b4d1f0..9ea36beb 100644 --- a/pkg/user/users.go +++ b/pkg/user/users.go @@ -20,7 +20,7 @@ import ( "sync" "time" - "github.com/fairdatasociety/fairOS-dfs/pkg/blockstore" + blockstore "github.com/asabya/swarm-blockstore" "github.com/fairdatasociety/fairOS-dfs/pkg/ensm" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" ) diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index ad59c7cb..c0453570 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -27,8 +27,8 @@ import ( "strconv" "strings" - "github.com/ethersphere/bee/pkg/bmtpool" - "github.com/ethersphere/bee/pkg/swarm" + "github.com/ethersphere/bee/v2/pkg/bmtpool" + "github.com/ethersphere/bee/v2/pkg/swarm" bmtlegacy "github.com/ethersphere/bmt/legacy" "golang.org/x/crypto/sha3" ) diff --git a/swagger/docs.go b/swagger/docs.go index 4777addc..1ecd8198 100644 --- a/swagger/docs.go +++ b/swagger/docs.go @@ -183,6 +183,58 @@ const docTemplate = `{ } } }, + "/public-pod-snapshot": { + "get": { + "description": "PodReceiveSnapshotHandler is the api handler to receive shared pod snapshot from shared reference", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "pod" + ], + "summary": "Receive shared pod snapshot", + "operationId": "pod-receive-snapshot-handler", + "parameters": [ + { + "type": "string", + "description": "pod sharing reference", + "name": "sharingRef", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/pod.DirSnapShot" + } + }, + "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", @@ -193,33 +245,448 @@ const docTemplate = `{ "application/json" ], "tags": [ - "public" + "public" + ], + "summary": "download file from a shared pod", + "parameters": [ + { + "type": "string", + "description": "pod sharing reference", + "name": "ref", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "file location in the pod", + "name": "file", + "in": "path", + "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" + } + } + } + } + }, + "/v1/act/act-shared-pods/{actName}": { + "get": { + "description": "ACTSharedPods is the api handler for listing pods shared in act.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "List pods in act", + "operationId": "list-shared-pod-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/act.Content" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/v1/act/grantee/{actName}": { + "get": { + "description": "ListGranteesHandler is the api handler for listing grantees in an existing act.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "List grantees in ACT", + "operationId": "list-grantee-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + }, + "post": { + "description": "CreateGranteeHandler is the api handler for creating act with grantee public key.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "Create ACT with grantee public key", + "operationId": "create-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "grantee public key", + "name": "grantee", + "in": "query", + "required": true + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + }, + "patch": { + "description": "GrantRevokeHandler is the api handler for granting and revoking access in an existing act.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "Grant ACT with grantee public key", + "operationId": "grant-revoke-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "grantee public key", + "name": "grant", + "in": "query" + }, + { + "type": "string", + "description": "revoke public key", + "name": "revoke", + "in": "query" + }, + { + "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/act/list": { + "get": { + "description": "ACTListHandler is the api handler for listing acts.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "List acts", + "operationId": "list-act", + "parameters": [ + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/act.List" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/v1/act/open-act-pod/{actName}": { + "post": { + "description": "ACTOpenPod is the api handler for opening pod in act.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "Open Act pod", + "operationId": "open-pod-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "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/act/save-act-pod/{actName}": { + "post": { + "description": "ACTSavePod is the api handler for saving shared act pod.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "Save shared acted pod in act list", + "operationId": "save-pod-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "description": "acted pod info", + "name": "content", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/act.Content" + } + }, + { + "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/act/share-pod/{actName}/{podname}": { + "post": { + "description": "ACTPodShareHandler is the api handler for adding a pod in act.", + "produces": [ + "application/json" + ], + "tags": [ + "act" ], - "summary": "download file from a shared pod", + "summary": "share a pod in act", + "operationId": "share-pod-act", "parameters": [ { "type": "string", - "description": "pod sharing reference", - "name": "ref", + "description": "unique act identifier", + "name": "actName", "in": "path", "required": true }, { "type": "string", - "description": "file location in the pod", - "name": "file", + "description": "pod to share in act", + "name": "podname", "in": "path", "required": true + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "type": "integer" - } + "$ref": "#/definitions/api.Content" } }, "400": { @@ -1816,6 +2283,13 @@ const docTemplate = `{ "in": "query", "required": true }, + { + "type": "string", + "description": "group name", + "name": "groupName", + "in": "query", + "required": true + }, { "type": "string", "description": "file path", @@ -4567,6 +5041,59 @@ const docTemplate = `{ } } }, + "/v2/user/login-with-signature": { + "post": { + "description": "login user with signature described in https://github.com/fairDataSociety/FIPs/blob/master/text/0063-external-account-generator.md", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Login User with signature", + "operationId": "user-login-signature", + "parameters": [ + { + "description": "signature and password", + "name": "user_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/common.UserSignatureLoginRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.UserLoginResponse" + }, + "headers": { + "Set-Cookie": { + "type": "string", + "description": "fairos-dfs session" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, "/v2/user/present": { "get": { "description": "checks if the new user is present in the new ENS based authentication", @@ -4658,6 +5185,67 @@ const docTemplate = `{ } }, "definitions": { + "act.Act": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/definitions/act.Content" + } + }, + "createdAt": { + "type": "string" + }, + "granteesRef": { + "type": "array", + "items": { + "type": "integer" + } + }, + "historyRef": { + "type": "array", + "items": { + "type": "integer" + } + }, + "name": { + "type": "string" + } + } + }, + "act.Content": { + "type": "object", + "properties": { + "addedAt": { + "type": "string" + }, + "owner": { + "type": "array", + "items": { + "type": "integer" + } + }, + "ownerPublicKey": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "topic": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "act.List": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/act.Act" + } + }, "api.Collection": { "type": "object", "properties": { @@ -4686,12 +5274,35 @@ const docTemplate = `{ } } }, + "api.Content": { + "type": "object", + "properties": { + "owner": { + "type": "string" + }, + "ownerPublicKey": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "topic": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, "api.DirModeRequest": { "type": "object", "properties": { "dirPath": { "type": "string" }, + "groupName": { + "type": "string" + }, "mode": { "type": "string" }, @@ -4717,6 +5328,9 @@ const docTemplate = `{ "dirPath": { "type": "string" }, + "groupName": { + "type": "string" + }, "podName": { "type": "string" } @@ -4809,6 +5423,9 @@ const docTemplate = `{ "filePath": { "type": "string" }, + "groupName": { + "type": "string" + }, "podName": { "type": "string" } @@ -4820,6 +5437,9 @@ const docTemplate = `{ "filePath": { "type": "string" }, + "groupName": { + "type": "string" + }, "mode": { "type": "string" }, @@ -4837,6 +5457,9 @@ const docTemplate = `{ "filePath": { "type": "string" }, + "groupName": { + "type": "string" + }, "podName": { "type": "string" } @@ -5264,6 +5887,9 @@ const docTemplate = `{ "common.RenameRequest": { "type": "object", "properties": { + "groupName": { + "type": "string" + }, "newPath": { "type": "string" }, @@ -5286,6 +5912,17 @@ const docTemplate = `{ } } }, + "common.UserSignatureLoginRequest": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "signature": { + "type": "string" + } + } + }, "common.UserSignupRequest": { "type": "object", "properties": { @@ -5390,6 +6027,50 @@ const docTemplate = `{ } } }, + "file.MetaData": { + "type": "object", + "properties": { + "accessTime": { + "type": "integer" + }, + "blockSize": { + "type": "integer" + }, + "compression": { + "type": "string" + }, + "contentType": { + "type": "string" + }, + "creationTime": { + "type": "integer" + }, + "fileInodeReference": { + "type": "array", + "items": { + "type": "integer" + } + }, + "fileName": { + "type": "string" + }, + "filePath": { + "type": "string" + }, + "fileSize": { + "type": "integer" + }, + "mode": { + "type": "integer" + }, + "modificationTime": { + "type": "integer" + }, + "version": { + "type": "integer" + } + } + }, "file.Stats": { "type": "object", "properties": { @@ -5428,6 +6109,47 @@ const docTemplate = `{ } } }, + "pod.DirSnapShot": { + "type": "object", + "properties": { + "accessTime": { + "type": "string" + }, + "blockSize": { + "type": "string" + }, + "contentType": { + "type": "string" + }, + "creationTime": { + "type": "string" + }, + "dirList": { + "type": "array", + "items": { + "$ref": "#/definitions/pod.DirSnapShot" + } + }, + "fileList": { + "type": "array", + "items": { + "$ref": "#/definitions/file.MetaData" + } + }, + "mode": { + "type": "integer" + }, + "modificationTime": { + "type": "string" + }, + "name": { + "type": "string" + }, + "size": { + "type": "string" + } + } + }, "pod.GroupItem": { "type": "object", "properties": { diff --git a/swagger/swagger.json b/swagger/swagger.json index cfd8e3fe..65fccb40 100644 --- a/swagger/swagger.json +++ b/swagger/swagger.json @@ -174,6 +174,58 @@ } } }, + "/public-pod-snapshot": { + "get": { + "description": "PodReceiveSnapshotHandler is the api handler to receive shared pod snapshot from shared reference", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "pod" + ], + "summary": "Receive shared pod snapshot", + "operationId": "pod-receive-snapshot-handler", + "parameters": [ + { + "type": "string", + "description": "pod sharing reference", + "name": "sharingRef", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/pod.DirSnapShot" + } + }, + "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", @@ -184,33 +236,448 @@ "application/json" ], "tags": [ - "public" + "public" + ], + "summary": "download file from a shared pod", + "parameters": [ + { + "type": "string", + "description": "pod sharing reference", + "name": "ref", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "file location in the pod", + "name": "file", + "in": "path", + "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" + } + } + } + } + }, + "/v1/act/act-shared-pods/{actName}": { + "get": { + "description": "ACTSharedPods is the api handler for listing pods shared in act.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "List pods in act", + "operationId": "list-shared-pod-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/act.Content" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/v1/act/grantee/{actName}": { + "get": { + "description": "ListGranteesHandler is the api handler for listing grantees in an existing act.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "List grantees in ACT", + "operationId": "list-grantee-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + }, + "post": { + "description": "CreateGranteeHandler is the api handler for creating act with grantee public key.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "Create ACT with grantee public key", + "operationId": "create-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "grantee public key", + "name": "grantee", + "in": "query", + "required": true + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + }, + "patch": { + "description": "GrantRevokeHandler is the api handler for granting and revoking access in an existing act.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "Grant ACT with grantee public key", + "operationId": "grant-revoke-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "grantee public key", + "name": "grant", + "in": "query" + }, + { + "type": "string", + "description": "revoke public key", + "name": "revoke", + "in": "query" + }, + { + "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/act/list": { + "get": { + "description": "ACTListHandler is the api handler for listing acts.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "List acts", + "operationId": "list-act", + "parameters": [ + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/act.List" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, + "/v1/act/open-act-pod/{actName}": { + "post": { + "description": "ACTOpenPod is the api handler for opening pod in act.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "Open Act pod", + "operationId": "open-pod-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "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/act/save-act-pod/{actName}": { + "post": { + "description": "ACTSavePod is the api handler for saving shared act pod.", + "produces": [ + "application/json" + ], + "tags": [ + "act" + ], + "summary": "Save shared acted pod in act list", + "operationId": "save-pod-act", + "parameters": [ + { + "type": "string", + "description": "unique act identifier", + "name": "actName", + "in": "path", + "required": true + }, + { + "description": "acted pod info", + "name": "content", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/act.Content" + } + }, + { + "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/act/share-pod/{actName}/{podname}": { + "post": { + "description": "ACTPodShareHandler is the api handler for adding a pod in act.", + "produces": [ + "application/json" + ], + "tags": [ + "act" ], - "summary": "download file from a shared pod", + "summary": "share a pod in act", + "operationId": "share-pod-act", "parameters": [ { "type": "string", - "description": "pod sharing reference", - "name": "ref", + "description": "unique act identifier", + "name": "actName", "in": "path", "required": true }, { "type": "string", - "description": "file location in the pod", - "name": "file", + "description": "pod to share in act", + "name": "podname", "in": "path", "required": true + }, + { + "type": "string", + "description": "cookie parameter", + "name": "Cookie", + "in": "header", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "type": "integer" - } + "$ref": "#/definitions/api.Content" } }, "400": { @@ -1807,6 +2274,13 @@ "in": "query", "required": true }, + { + "type": "string", + "description": "group name", + "name": "groupName", + "in": "query", + "required": true + }, { "type": "string", "description": "file path", @@ -4558,6 +5032,59 @@ } } }, + "/v2/user/login-with-signature": { + "post": { + "description": "login user with signature described in https://github.com/fairDataSociety/FIPs/blob/master/text/0063-external-account-generator.md", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Login User with signature", + "operationId": "user-login-signature", + "parameters": [ + { + "description": "signature and password", + "name": "user_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/common.UserSignatureLoginRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.UserLoginResponse" + }, + "headers": { + "Set-Cookie": { + "type": "string", + "description": "fairos-dfs session" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.response" + } + } + } + } + }, "/v2/user/present": { "get": { "description": "checks if the new user is present in the new ENS based authentication", @@ -4649,6 +5176,67 @@ } }, "definitions": { + "act.Act": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/definitions/act.Content" + } + }, + "createdAt": { + "type": "string" + }, + "granteesRef": { + "type": "array", + "items": { + "type": "integer" + } + }, + "historyRef": { + "type": "array", + "items": { + "type": "integer" + } + }, + "name": { + "type": "string" + } + } + }, + "act.Content": { + "type": "object", + "properties": { + "addedAt": { + "type": "string" + }, + "owner": { + "type": "array", + "items": { + "type": "integer" + } + }, + "ownerPublicKey": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "topic": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "act.List": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/act.Act" + } + }, "api.Collection": { "type": "object", "properties": { @@ -4677,12 +5265,35 @@ } } }, + "api.Content": { + "type": "object", + "properties": { + "owner": { + "type": "string" + }, + "ownerPublicKey": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "topic": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, "api.DirModeRequest": { "type": "object", "properties": { "dirPath": { "type": "string" }, + "groupName": { + "type": "string" + }, "mode": { "type": "string" }, @@ -4708,6 +5319,9 @@ "dirPath": { "type": "string" }, + "groupName": { + "type": "string" + }, "podName": { "type": "string" } @@ -4800,6 +5414,9 @@ "filePath": { "type": "string" }, + "groupName": { + "type": "string" + }, "podName": { "type": "string" } @@ -4811,6 +5428,9 @@ "filePath": { "type": "string" }, + "groupName": { + "type": "string" + }, "mode": { "type": "string" }, @@ -4828,6 +5448,9 @@ "filePath": { "type": "string" }, + "groupName": { + "type": "string" + }, "podName": { "type": "string" } @@ -5255,6 +5878,9 @@ "common.RenameRequest": { "type": "object", "properties": { + "groupName": { + "type": "string" + }, "newPath": { "type": "string" }, @@ -5277,6 +5903,17 @@ } } }, + "common.UserSignatureLoginRequest": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "signature": { + "type": "string" + } + } + }, "common.UserSignupRequest": { "type": "object", "properties": { @@ -5381,6 +6018,50 @@ } } }, + "file.MetaData": { + "type": "object", + "properties": { + "accessTime": { + "type": "integer" + }, + "blockSize": { + "type": "integer" + }, + "compression": { + "type": "string" + }, + "contentType": { + "type": "string" + }, + "creationTime": { + "type": "integer" + }, + "fileInodeReference": { + "type": "array", + "items": { + "type": "integer" + } + }, + "fileName": { + "type": "string" + }, + "filePath": { + "type": "string" + }, + "fileSize": { + "type": "integer" + }, + "mode": { + "type": "integer" + }, + "modificationTime": { + "type": "integer" + }, + "version": { + "type": "integer" + } + } + }, "file.Stats": { "type": "object", "properties": { @@ -5419,6 +6100,47 @@ } } }, + "pod.DirSnapShot": { + "type": "object", + "properties": { + "accessTime": { + "type": "string" + }, + "blockSize": { + "type": "string" + }, + "contentType": { + "type": "string" + }, + "creationTime": { + "type": "string" + }, + "dirList": { + "type": "array", + "items": { + "$ref": "#/definitions/pod.DirSnapShot" + } + }, + "fileList": { + "type": "array", + "items": { + "$ref": "#/definitions/file.MetaData" + } + }, + "mode": { + "type": "integer" + }, + "modificationTime": { + "type": "string" + }, + "name": { + "type": "string" + }, + "size": { + "type": "string" + } + } + }, "pod.GroupItem": { "type": "object", "properties": { diff --git a/swagger/swagger.yaml b/swagger/swagger.yaml index 49e38142..f17e96b3 100644 --- a/swagger/swagger.yaml +++ b/swagger/swagger.yaml @@ -1,4 +1,44 @@ definitions: + act.Act: + properties: + content: + items: + $ref: '#/definitions/act.Content' + type: array + createdAt: + type: string + granteesRef: + items: + type: integer + type: array + historyRef: + items: + type: integer + type: array + name: + type: string + type: object + act.Content: + properties: + addedAt: + type: string + owner: + items: + type: integer + type: array + ownerPublicKey: + type: string + reference: + type: string + topic: + items: + type: integer + type: array + type: object + act.List: + additionalProperties: + $ref: '#/definitions/act.Act' + type: object api.Collection: properties: indexes: @@ -17,10 +57,25 @@ definitions: $ref: '#/definitions/api.Collection' type: array type: object + api.Content: + properties: + owner: + type: string + ownerPublicKey: + type: string + reference: + type: string + topic: + items: + type: integer + type: array + type: object api.DirModeRequest: properties: dirPath: type: string + groupName: + type: string mode: type: string podName: @@ -37,6 +92,8 @@ definitions: properties: dirPath: type: string + groupName: + type: string podName: type: string type: object @@ -96,6 +153,8 @@ definitions: properties: filePath: type: string + groupName: + type: string podName: type: string type: object @@ -103,6 +162,8 @@ definitions: properties: filePath: type: string + groupName: + type: string mode: type: string podName: @@ -114,6 +175,8 @@ definitions: type: string filePath: type: string + groupName: + type: string podName: type: string type: object @@ -387,6 +450,8 @@ definitions: type: object common.RenameRequest: properties: + groupName: + type: string newPath: type: string oldPath: @@ -401,6 +466,13 @@ definitions: userName: type: string type: object + common.UserSignatureLoginRequest: + properties: + password: + type: string + signature: + type: string + type: object common.UserSignupRequest: properties: mnemonic: @@ -469,6 +541,35 @@ definitions: size: type: string type: object + file.MetaData: + properties: + accessTime: + type: integer + blockSize: + type: integer + compression: + type: string + contentType: + type: string + creationTime: + type: integer + fileInodeReference: + items: + type: integer + type: array + fileName: + type: string + filePath: + type: string + fileSize: + type: integer + mode: + type: integer + modificationTime: + type: integer + version: + type: integer + type: object file.Stats: properties: accessTime: @@ -494,6 +595,33 @@ definitions: podName: type: string type: object + pod.DirSnapShot: + properties: + accessTime: + type: string + blockSize: + type: string + contentType: + type: string + creationTime: + type: string + dirList: + items: + $ref: '#/definitions/pod.DirSnapShot' + type: array + fileList: + items: + $ref: '#/definitions/file.MetaData' + type: array + mode: + type: integer + modificationTime: + type: string + name: + type: string + size: + type: string + type: object pod.GroupItem: properties: name: @@ -673,6 +801,42 @@ paths: summary: get key from public pod tags: - public + /public-pod-snapshot: + get: + consumes: + - application/json + description: PodReceiveSnapshotHandler is the api handler to receive shared + pod snapshot from shared reference + operationId: pod-receive-snapshot-handler + parameters: + - description: pod sharing reference + in: query + name: sharingRef + required: true + type: string + - description: cookie parameter + in: header + name: Cookie + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/pod.DirSnapShot' + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: Receive shared pod snapshot + tags: + - pod /public/{ref}/{file}: get: consumes: @@ -710,6 +874,289 @@ paths: summary: download file from a shared pod tags: - public + /v1/act/act-shared-pods/{actName}: + get: + description: ACTSharedPods is the api handler for listing pods shared in act. + operationId: list-shared-pod-act + parameters: + - description: unique act identifier + in: path + name: actName + required: true + type: string + - description: cookie parameter + in: header + name: Cookie + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/act.Content' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: List pods in act + tags: + - act + /v1/act/grantee/{actName}: + get: + description: ListGranteesHandler is the api handler for listing grantees in + an existing act. + operationId: list-grantee-act + parameters: + - description: unique act identifier + in: path + name: actName + required: true + type: string + - description: cookie parameter + in: header + name: Cookie + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + type: string + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: List grantees in ACT + tags: + - act + patch: + description: GrantRevokeHandler is the api handler for granting and revoking + access in an existing act. + operationId: grant-revoke-act + parameters: + - description: unique act identifier + in: path + name: actName + required: true + type: string + - description: grantee public key + in: query + name: grant + type: string + - description: revoke public key + in: query + name: revoke + type: string + - 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: Grant ACT with grantee public key + tags: + - act + post: + description: CreateGranteeHandler is the api handler for creating act with grantee + public key. + operationId: create-act + parameters: + - description: unique act identifier + in: path + name: actName + required: true + type: string + - description: grantee public key + in: query + name: grantee + required: true + type: string + produces: + - application/json + responses: + "201": + description: Created + 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: Create ACT with grantee public key + tags: + - act + /v1/act/list: + get: + description: ACTListHandler is the api handler for listing acts. + operationId: list-act + parameters: + - description: cookie parameter + in: header + name: Cookie + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/act.List' + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: List acts + tags: + - act + /v1/act/open-act-pod/{actName}: + post: + description: ACTOpenPod is the api handler for opening pod in act. + operationId: open-pod-act + parameters: + - description: unique act identifier + in: path + name: actName + required: true + type: string + - 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: Open Act pod + tags: + - act + /v1/act/save-act-pod/{actName}: + post: + description: ACTSavePod is the api handler for saving shared act pod. + operationId: save-pod-act + parameters: + - description: unique act identifier + in: path + name: actName + required: true + type: string + - description: acted pod info + in: body + name: content + required: true + schema: + $ref: '#/definitions/act.Content' + - 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: Save shared acted pod in act list + tags: + - act + /v1/act/share-pod/{actName}/{podname}: + post: + description: ACTPodShareHandler is the api handler for adding a pod in act. + operationId: share-pod-act + parameters: + - description: unique act identifier + in: path + name: actName + required: true + type: string + - description: pod to share in act + in: path + name: podname + required: true + type: string + - description: cookie parameter + in: header + name: Cookie + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Content' + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: share a pod in act + tags: + - act /v1/dir/chmod: post: consumes: @@ -1794,6 +2241,11 @@ paths: name: podName required: true type: string + - description: group name + in: query + name: groupName + required: true + type: string - description: file path in: query name: filePath @@ -3659,6 +4111,41 @@ paths: summary: Login User tags: - user + /v2/user/login-with-signature: + post: + consumes: + - application/json + description: login user with signature described in https://github.com/fairDataSociety/FIPs/blob/master/text/0063-external-account-generator.md + operationId: user-login-signature + parameters: + - description: signature and password + in: body + name: user_request + required: true + schema: + $ref: '#/definitions/common.UserSignatureLoginRequest' + produces: + - application/json + responses: + "200": + description: OK + headers: + Set-Cookie: + description: fairos-dfs session + type: string + schema: + $ref: '#/definitions/api.UserLoginResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.response' + summary: Login User with signature + tags: + - user /v2/user/present: get: description: checks if the new user is present in the new ENS based authentication diff --git a/wasm/main.go b/wasm/main.go index 445865e8..de1a27cf 100644 --- a/wasm/main.go +++ b/wasm/main.go @@ -11,6 +11,7 @@ import ( "fmt" "io" "os" + "path/filepath" "strings" "syscall/js" @@ -18,6 +19,7 @@ import ( "github.com/fairdatasociety/fairOS-dfs/pkg/collection" "github.com/fairdatasociety/fairOS-dfs/pkg/contracts" "github.com/fairdatasociety/fairOS-dfs/pkg/dfs" + "github.com/fairdatasociety/fairOS-dfs/pkg/file" "github.com/fairdatasociety/fairOS-dfs/pkg/logging" "github.com/fairdatasociety/fairOS-dfs/pkg/utils" "github.com/sirupsen/logrus" @@ -45,6 +47,7 @@ func registerWasmFunctions() { js.Global().Set("connectWallet", js.FuncOf(connectWallet)) js.Global().Set("login", js.FuncOf(login)) js.Global().Set("walletLogin", js.FuncOf(walletLogin)) + js.Global().Set("signatureLogin", js.FuncOf(signatureLogin)) js.Global().Set("userPresent", js.FuncOf(userPresent)) js.Global().Set("userIsLoggedIn", js.FuncOf(userIsLoggedIn)) js.Global().Set("userLogout", js.FuncOf(userLogout)) @@ -133,6 +136,11 @@ func registerWasmFunctions() { js.Global().Set("docEntryDelete", js.FuncOf(docEntryDelete)) js.Global().Set("docLoadJson", js.FuncOf(docLoadJson)) js.Global().Set("docIndexJson", js.FuncOf(docIndexJson)) + + js.Global().Set("publicPodFile", js.FuncOf(publicPodFile)) + js.Global().Set("publicPodFileMeta", js.FuncOf(publicPodFileMeta)) + js.Global().Set("publicPodDir", js.FuncOf(publicPodDir)) + js.Global().Set("publicPodReceiveInfo", js.FuncOf(publicPodReceiveInfo)) } func connect(_ js.Value, funcArgs []js.Value) interface{} { @@ -170,7 +178,7 @@ func connect(_ js.Value, funcArgs []js.Value) interface{} { if subContractAddress != "" { subConfig.DataHubAddress = subContractAddress } - logger := logging.New(os.Stdout, logrus.DebugLevel) + logger := logging.New(os.Stdout, logrus.ErrorLevel) go func() { var err error @@ -188,6 +196,7 @@ func connect(_ js.Value, funcArgs []js.Value) interface{} { if err != nil { reject.Invoke(fmt.Sprintf("failed to connect to fairOS: %s", err.Error())) } + fmt.Println("******** FairOS connected ********") resolve.Invoke("connected") }() @@ -207,7 +216,10 @@ 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 api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"publicKvEntryGet(sharingRef, tableName, key)\"") return nil @@ -254,6 +266,10 @@ func login(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"login(username, password)\"") @@ -290,6 +306,10 @@ 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 api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"walletLogin(addressHex, signature)\"") @@ -321,10 +341,51 @@ func walletLogin(_ js.Value, funcArgs []js.Value) interface{} { return promiseConstructor.New(handler) } +func signatureLogin(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } + + if len(funcArgs) != 2 { + reject.Invoke("not enough arguments. \"signatureLogin(signature, password)\"") + return nil + } + signature := funcArgs[0].String() + password := funcArgs[1].String() + + go func() { + lr, err := api.LoginUserWithSignature(signature, password, "") + if err != nil { + reject.Invoke(fmt.Sprintf("Failed to login user : %s", err.Error())) + return + } + ui := lr.UserInfo + object := js.Global().Get("Object").New() + object.Set("user", ui.GetUserName()) + object.Set("address", lr.Address) + 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 api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"connectWallet(username, password, walletAddress, signature)\"") @@ -355,6 +416,10 @@ func userPresent(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 1 { reject.Invoke("not enough arguments. \"userPresent(username)\"") @@ -380,6 +445,10 @@ func userIsLoggedIn(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 1 { reject.Invoke("not enough arguments. \"userIsLoggedIn(username)\"") @@ -406,6 +475,10 @@ func userLogout(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 1 { reject.Invoke("not enough arguments. \"userLogout(sessionId)\"") @@ -432,6 +505,10 @@ func userDelete(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"userDelete(sessionId, password)\"") @@ -459,6 +536,10 @@ func userStat(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 1 { reject.Invoke("not enough arguments. \"userStat(sessionId)\"") @@ -490,6 +571,10 @@ func podNew(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"podNew(sessionId, podName)\"") @@ -517,6 +602,10 @@ func podOpen(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"podOpen(sessionId, podName)\"") @@ -544,6 +633,10 @@ func podClose(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"podClose(sessionId, podName)\"") @@ -571,6 +664,10 @@ func podSync(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"podSync(sessionId, podName)\"") @@ -598,6 +695,10 @@ func podDelete(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"podDelete(sessionId, podName)\"") @@ -625,6 +726,10 @@ func podList(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 1 { reject.Invoke("not enough arguments. \"podList(sessionId)\"") @@ -666,6 +771,10 @@ func podStat(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"podStat(sessionId, podName)\"") @@ -697,6 +806,10 @@ func podShare(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"podShare(sessionId, podName, shareAs)\"") @@ -728,6 +841,10 @@ func podReceive(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"podReceive(sessionId, newPodName, podSharingReference)\"") @@ -757,10 +874,182 @@ func podReceive(_ js.Value, funcArgs []js.Value) interface{} { return promiseConstructor.New(handler) } +func publicPodFile(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } + + if len(funcArgs) != 2 { + reject.Invoke("not enough arguments. \"publicPod(podSharingReference, filepath)\"") + return nil + } + podSharingReference := funcArgs[0].String() + fp := funcArgs[1].String() + + go func() { + ref, err := utils.ParseHexReference(podSharingReference) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod downlod failed : %s", err.Error())) + return + } + shareInfo, err := api.PublicPodReceiveInfo(ref) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod downlod failed : %s", err.Error())) + return + } + r, _, err := api.PublicPodFileDownload(shareInfo, fp) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod fileDownload failed : %s", err.Error())) + return + } + defer r.Close() + + buf := new(bytes.Buffer) + _, err = buf.ReadFrom(r) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod fileDownload failed : %s", err.Error())) + return + } + a := js.Global().Get("Uint8Array").New(buf.Len()) + js.CopyBytesToJS(a, buf.Bytes()) + resolve.Invoke(a) + }() + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + +func publicPodFileMeta(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } + + if len(funcArgs) != 1 { + reject.Invoke("not enough arguments. \"publicPodFileMeta(metadata)\"") + return nil + } + metadata := funcArgs[0].String() + meta := &file.MetaData{} + err := json.Unmarshal([]byte(metadata), meta) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod file meta failed : %s", err.Error())) + return nil + } + go func() { + + r, _, err := api.PublicPodFileDownloadFromMetadata(meta) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod fileDownload failed : %s", err.Error())) + return + } + defer r.Close() + buf := new(bytes.Buffer) + _, err = buf.ReadFrom(r) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod fileDownload failed : %s", err.Error())) + return + } + a := js.Global().Get("Uint8Array").New(buf.Len()) + js.CopyBytesToJS(a, buf.Bytes()) + resolve.Invoke(a) + }() + return nil + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + +func publicPodDir(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } + + if len(funcArgs) != 2 { + reject.Invoke("not enough arguments. \"publicPodDir(podSharingReference, filepath)\"") + return nil + } + podSharingReference := funcArgs[0].String() + fp := funcArgs[1].String() + + go func() { + ref, err := utils.ParseHexReference(podSharingReference) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod downlod failed : %s", err.Error())) + return + } + shareInfo, err := api.PublicPodReceiveInfo(ref) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod downlod failed : %s", err.Error())) + return + } + filePath := filepath.ToSlash(fp) + dirs, files, err := api.PublicPodDisLs(shareInfo, filePath) + if err != nil { + reject.Invoke(fmt.Sprintf("public pod fileDownload failed : %s", err.Error())) + return + } + 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 + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + func podReceiveInfo(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"podReceiveInfo(sessionId, pod_sharing_reference)\"") @@ -796,10 +1085,56 @@ func podReceiveInfo(_ js.Value, funcArgs []js.Value) interface{} { return promiseConstructor.New(handler) } +func publicPodReceiveInfo(_ js.Value, funcArgs []js.Value) interface{} { + handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { + resolve := args[0] + reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } + + if len(funcArgs) != 1 { + reject.Invoke("not enough arguments. \"publicPodReceiveInfo(pod_sharing_reference)\"") + return nil + } + podSharingReference := funcArgs[0].String() + + go func() { + ref, err := utils.ParseHexReference(podSharingReference) + if err != nil { + reject.Invoke(fmt.Sprintf("publicPodReceiveInfo failed : %s", err.Error())) + return + } + shareInfo, err := api.PublicPodReceiveInfo(ref) + if err != nil { + reject.Invoke(fmt.Sprintf("publicPodReceiveInfo failed : %s", err.Error())) + return + } + + 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 + }) + + promiseConstructor := js.Global().Get("Promise") + return promiseConstructor.New(handler) +} + func groupNew(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"groupNew(sessionId, groupName)\"") @@ -827,6 +1162,10 @@ func groupOpen(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"groupOpen(sessionId, groupName)\"") @@ -854,6 +1193,10 @@ func groupClose(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"groupClose(sessionId, groupName)\"") @@ -881,6 +1224,10 @@ func groupDelete(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"groupDelete(sessionId, groupName)\"") @@ -908,6 +1255,10 @@ func groupDeleteShared(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"groupDeleteShared(sessionId, groupName)\"") @@ -935,6 +1286,10 @@ func groupList(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 1 { reject.Invoke("not enough arguments. \"groupList(sessionId)\"") @@ -976,6 +1331,10 @@ func groupInvite(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"groupInvite(sessionId, groupName, member, permission)\"") @@ -1008,6 +1367,10 @@ func groupAccept(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"groupInvite(sessionId, groupInviteReference)\"") @@ -1035,6 +1398,10 @@ func groupRemoveMember(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"groupRemoveMember(sessionId, groupName, member)\"") @@ -1063,6 +1430,10 @@ func groupUpdatePermission(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"groupUpdatePermission(sessionId, groupName, member, permission)\"") @@ -1093,6 +1464,10 @@ func groupMembers(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"groupMembers(sessionId, groupName)\"") @@ -1125,6 +1500,10 @@ func groupPermission(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"groupPermission(sessionId, groupName)\"") @@ -1155,6 +1534,10 @@ func dirPresent(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"dirPresent(sessionId, podName, dirPath)\"") @@ -1187,6 +1570,10 @@ func dirMake(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"dirMake(sessionId, podName, dirPath)\"") @@ -1215,6 +1602,10 @@ func dirRemove(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"dirRemove(sessionId, podName, dirPath)\"") @@ -1243,6 +1634,10 @@ func dirList(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"dirList(sessionId, podName, dirPath)\"") @@ -1301,6 +1696,10 @@ func dirStat(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"dirStat(sessionId, podName, dirPath)\"") @@ -1340,6 +1739,10 @@ func fileDownload(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"fileDownload(sessionId, podName, filePath)\"") return nil @@ -1376,6 +1779,10 @@ func fileUpload(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 8 { reject.Invoke("not enough arguments. \"fileUpload(sessionId, podName, dirPath, file, name, size, blockSize, compression)\"") return nil @@ -1422,6 +1829,10 @@ func fileShare(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"fileShare(sessionId, podName, dirPath, destinationUser)\"") @@ -1455,6 +1866,10 @@ func fileReceive(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"fileReceive(sessionId, podName, directory, file_sharing_reference)\"") @@ -1487,6 +1902,10 @@ func fileReceiveInfo(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"fileReceiveInfo(sessionId, fileSharingReference)\"") @@ -1525,6 +1944,10 @@ func fileDelete(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"fileDelete(sessionId, podName, podFileWithPath)\"") @@ -1553,6 +1976,10 @@ func fileStat(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"fileStat(sessionId, podName, podFileWithPath)\"") @@ -1594,6 +2021,10 @@ func groupDirPresent(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"groupDirPresent(sessionId, groupName, dirPath)\"") @@ -1626,6 +2057,10 @@ func groupDirMake(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"groupDirMake(sessionId, groupName, dirPath)\"") @@ -1654,6 +2089,10 @@ func groupDirRemove(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"groupDirRemove(sessionId, groupName, dirPath)\"") @@ -1682,6 +2121,10 @@ func groupDirList(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"groupDirList(sessionId, groupName, dirPath)\"") @@ -1740,6 +2183,10 @@ func groupDirStat(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"groupDirStat(sessionId, groupName, dirPath)\"") @@ -1779,6 +2226,10 @@ func groupFileDownload(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"groupFileDownload(sessionId, groupName, filePath)\"") return nil @@ -1798,7 +2249,7 @@ func groupFileDownload(_ js.Value, funcArgs []js.Value) interface{} { buf := new(bytes.Buffer) _, err = buf.ReadFrom(r) if err != nil { - reject.Invoke(fmt.Sprintf("groupFileDownload failed : %s", err.Error())) + reject.Invoke(fmt.Sprintf("fileDownload failed : %s", err.Error())) return } a := js.Global().Get("Uint8Array").New(buf.Len()) @@ -1815,6 +2266,10 @@ func groupFileUpload(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 8 { reject.Invoke("not enough arguments. \"groupFileUpload(sessionId, groupName, dirPath, file, name, size, blockSize, compression)\"") return nil @@ -1861,6 +2316,10 @@ func groupFileShare(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"groupFileShare(sessionId, groupName, dirPath, destinationUser)\"") @@ -1894,6 +2353,10 @@ func groupFileDelete(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"groupFileDelete(sessionId, groupName, podFileWithPath)\"") @@ -1922,6 +2385,10 @@ func groupFileStat(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"groupFileStat(sessionId, groupName, podFileWithPath)\"") @@ -1963,6 +2430,10 @@ func kvNewStore(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"kvNewStore(sessionId, podName, tableName, indexType)\"") @@ -2007,6 +2478,10 @@ func kvList(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"kvList(sessionId, podName)\"") @@ -2043,6 +2518,10 @@ func kvOpen(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"kvOpen(sessionId, podName, tableName)\"") @@ -2071,6 +2550,10 @@ func kvDelete(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"kvDelete(sessionId, podName, tableName)\"") @@ -2099,6 +2582,10 @@ func kvCount(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"kvCount(sessionId, podName, tableName)\"") @@ -2130,6 +2617,10 @@ func kvEntryPut(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 5 { reject.Invoke("not enough arguments. \"kvEntryPut(sessionId, podName, tableName, key, value)\"") @@ -2165,6 +2656,10 @@ func kvEntryGet(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"kvEntryGet(sessionId, podName, tableName, key)\"") @@ -2198,6 +2693,10 @@ func kvEntryDelete(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"kvEntryDelete(sessionId, podName, tableName, key)\"") @@ -2227,6 +2726,10 @@ func kvLoadCSV(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"kvLoadCSV(sessionId, podName, tableName, file)\"") return nil @@ -2304,6 +2807,10 @@ func kvSeek(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 6 { reject.Invoke("not enough arguments. \"kvSeek(sessionId, podName, tableName, start, end, limit)\"") @@ -2338,6 +2845,10 @@ func kvSeekNext(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"kvSeekNext(sessionId, podName, tableName)\"") @@ -2371,6 +2882,10 @@ func docNewStore(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 5 { reject.Invoke("not enough arguments. \"docNewStore(sessionId, podName, tableName, simpleIndexes, mutable)\"") @@ -2426,6 +2941,10 @@ func docList(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"docList(sessionId, podName)\"") @@ -2454,6 +2973,10 @@ func docOpen(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"docOpen(sessionId, podName, tableName)\"") @@ -2482,6 +3005,10 @@ func docCount(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"docCount(sessionId, podName, tableName, expression)\"") @@ -2512,6 +3039,10 @@ func docDelete(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"docDelete(sessionId, podName, tableName)\"") @@ -2540,6 +3071,10 @@ func docFind(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 5 { reject.Invoke("not enough arguments. \"docFind(sessionId, podName, tableName, expression, limit)\"") @@ -2571,6 +3106,10 @@ func docEntryPut(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"docEntryPut(sessionId, podName, tableName, value)\"") @@ -2604,6 +3143,10 @@ func docEntryGet(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"docEntryGet(sessionId, podName, tableName, id)\"") @@ -2637,6 +3180,10 @@ func docEntryDelete(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"docEntryDelete(sessionId, podName, tableName, id)\"") @@ -2666,6 +3213,10 @@ func docLoadJson(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"docLoadJson(sessionId, podName, tableName, file)\"") return nil @@ -2724,6 +3275,10 @@ func docIndexJson(_ js.Value, funcArgs []js.Value) interface{} { handler := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] + if api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 4 { reject.Invoke("not enough arguments. \"docIndexJson(sessionId, podName, tableName, filePath)\"") @@ -2753,6 +3308,10 @@ 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 api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"encryptSubscription(sessionId, podName, subscriberNameHash)\"") @@ -2792,6 +3351,10 @@ 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 api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"getSubscriptions(sessionId)\"") @@ -2831,6 +3394,10 @@ 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 api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"openSubscribedPod(sessionId, subHash, keyLocation)\"") @@ -2869,6 +3436,10 @@ 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 api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 3 { reject.Invoke("not enough arguments. \"openSubscribedPodFromReference(sessionId, reference, sellerNameHash)\"") @@ -2907,6 +3478,10 @@ 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 api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 1 { reject.Invoke("not enough arguments. \"getSubscribablePods(sessionId)\"") @@ -2950,6 +3525,10 @@ 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 api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 1 { reject.Invoke("not enough arguments. \"getSubRequests(sessionId)\"") @@ -2987,6 +3566,10 @@ 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 api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"getSubscribablePodInfo(sessionId, subHash)\"") @@ -3033,6 +3616,10 @@ 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 api == nil { + reject.Invoke("not connected to fairOS") + return nil + } if len(funcArgs) != 2 { reject.Invoke("not enough arguments. \"getNameHash(sessionId, username)\"")