Skip to content

Commit

Permalink
Merge pull request #185 from numary/feature/num-443-ledger-allow-to-f…
Browse files Browse the repository at this point in the history
…ilter-accounts-using-a

feat: Add accounts filtering on address or metadata
  • Loading branch information
gfyrag authored Apr 7, 2022
2 parents 044fbc0 + d49a84b commit 68b417c
Show file tree
Hide file tree
Showing 24 changed files with 581 additions and 129 deletions.
8 changes: 5 additions & 3 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,16 @@ func TestServer(t *testing.T) {
timeout := 5 * time.Second
delay := 200 * time.Millisecond
for {
_, err := http.DefaultClient.Get("http://localhost:3068/_info")
if err != nil {
rsp, err := http.DefaultClient.Get("http://localhost:3068/_info")
if err != nil || rsp.StatusCode != http.StatusOK {
if counter*delay < timeout {
counter++
<-time.After(delay)
continue
}
assert.FailNow(t, err.Error())
if assert.FailNow(t, err.Error()) {
return
}
}
break
}
Expand Down
36 changes: 18 additions & 18 deletions cmd/server_start.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,24 @@ func NewServerStart() *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
app := NewContainer(
viper.GetViper(),
fx.Invoke(func(h *api.API) error {
listener, err := net.Listen("tcp", viper.GetString(serverHttpBindAddressFlag))
if err != nil {
return err
}

go http.Serve(listener, h)
go func() {
select {
case <-cmd.Context().Done():
}
err := listener.Close()
if err != nil {
panic(err)
}
}()

return nil
fx.Invoke(func(lc fx.Lifecycle, h *api.API) {
var (
err error
listener net.Listener
)
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
listener, err = net.Listen("tcp", viper.GetString(serverHttpBindAddressFlag))
if err != nil {
return err
}
go http.Serve(listener, h)
return nil
},
OnStop: func(ctx context.Context) error {
return listener.Close()
},
})
}),
)
errCh := make(chan error, 1)
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ require (
github.com/ThreeDotsLabs/watermill-http v1.1.4 // indirect
github.com/ThreeDotsLabs/watermill-kafka/v2 v2.2.1 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211226235153-13a0add2f557 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cenkalti/backoff/v4 v4.1.2 // indirect
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
Expand Down
2 changes: 1 addition & 1 deletion internal/pgtesting/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (s *PGServer) Close() error {
return s.close()
}

const MaxConnections = 2
const MaxConnections = 3

func PostgresServer() (*PGServer, error) {

Expand Down
5 changes: 5 additions & 0 deletions pkg/api/controllers/account_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ func NewAccountController() AccountController {

func (ctl *AccountController) GetAccounts(c *gin.Context) {
l, _ := c.Get("ledger")

cursor, err := l.(*ledger.Ledger).FindAccounts(
c.Request.Context(),
query.After(c.Query("after")),
query.Address(c.Query("address")),
func(q *query.Query) {
q.Params["metadata"] = c.QueryMap("metadata")
},
)
if err != nil {
ResponseError(c, err)
Expand Down
107 changes: 100 additions & 7 deletions pkg/api/controllers/account_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"go.uber.org/fx"
"net/http"
"net/url"
"testing"
)

Expand All @@ -27,7 +28,9 @@ func TestGetAccounts(t *testing.T) {
},
},
})
assert.Equal(t, http.StatusOK, rsp.Result().StatusCode)
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}

rsp = internal.PostTransaction(t, h, core.TransactionData{
Postings: core.Postings{
Expand All @@ -39,14 +42,104 @@ func TestGetAccounts(t *testing.T) {
},
},
})
assert.Equal(t, http.StatusOK, rsp.Result().StatusCode)
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}

rsp = internal.GetAccounts(h)
assert.Equal(t, http.StatusOK, rsp.Result().StatusCode)
rsp = internal.PostAccountMetadata(t, h, "bob", core.Metadata{
"roles": json.RawMessage(`"admin"`),
"accountId": json.RawMessage("3"),
"enabled": json.RawMessage(`"true"`),
"a": json.RawMessage(`{"nested": {"key": "hello"}}`),
})
if !assert.Equal(t, http.StatusNoContent, rsp.Result().StatusCode) {
return nil
}

rsp = internal.GetAccounts(h, url.Values{})
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}

cursor := internal.DecodeCursorResponse(t, rsp.Body, core.Account{})
assert.EqualValues(t, 3, cursor.Total)
assert.Len(t, cursor.Data, 3)
if !assert.EqualValues(t, 3, cursor.Total) {
return nil
}
if !assert.Len(t, cursor.Data, 3) {
return nil
}

rsp = internal.GetAccounts(h, url.Values{
"metadata[roles]": []string{"admin"},
})
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}

cursor = internal.DecodeCursorResponse(t, rsp.Body, core.Account{})
if !assert.EqualValues(t, 1, cursor.Total) {
return nil
}
if !assert.Len(t, cursor.Data, 1) {
return nil
}

rsp = internal.GetAccounts(h, url.Values{
"metadata[accountId]": []string{"3"},
})
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}

cursor = internal.DecodeCursorResponse(t, rsp.Body, core.Account{})
if !assert.EqualValues(t, 1, cursor.Total) {
return nil
}
if !assert.Len(t, cursor.Data, 1) {
return nil
}

rsp = internal.GetAccounts(h, url.Values{
"metadata[enabled]": []string{"true"},
})
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}

cursor = internal.DecodeCursorResponse(t, rsp.Body, core.Account{})
if !assert.EqualValues(t, 1, cursor.Total) {
return nil
}
if !assert.Len(t, cursor.Data, 1) {
return nil
}

rsp = internal.GetAccounts(h, url.Values{
"metadata[a.nested.key]": []string{"hello"},
})
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}

cursor = internal.DecodeCursorResponse(t, rsp.Body, core.Account{})
if !assert.EqualValues(t, 1, cursor.Total) {
return nil
}
if !assert.Len(t, cursor.Data, 1) {
return nil
}

rsp = internal.GetAccounts(h, url.Values{
"metadata[unknown]": []string{"key"},
})
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}

cursor = internal.DecodeCursorResponse(t, rsp.Body, core.Account{})
if !assert.EqualValues(t, 0, cursor.Total) {
return nil
}
return nil
},
})
Expand Down Expand Up @@ -88,7 +181,7 @@ func TestGetAccount(t *testing.T) {
},
Volumes: map[string]map[string]int64{
"USD": {
"input": 100,
"input": 100,
"output": 0,
},
},
Expand Down
8 changes: 5 additions & 3 deletions pkg/api/controllers/config_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,30 @@ import (
"github.com/numary/ledger/pkg/api"
"github.com/numary/ledger/pkg/api/controllers"
"github.com/numary/ledger/pkg/api/internal"
"github.com/numary/ledger/pkg/storage"
"github.com/stretchr/testify/assert"
"go.uber.org/fx"
"net/http"
"testing"
)

func TestGetInfo(t *testing.T) {
internal.RunTest(t, fx.Invoke(func(lc fx.Lifecycle, h *api.API) {
internal.RunTest(t, fx.Invoke(func(lc fx.Lifecycle, h *api.API, driver storage.Driver) {
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
rsp := internal.GetInfo(h)
assert.Equal(t, http.StatusOK, rsp.Result().StatusCode)

info := controllers.ConfigInfo{}
internal.DecodeSingleResponse(t, rsp.Body, &info)
info.Config.LedgerStorage.Ledgers = []string{}
assert.EqualValues(t, controllers.ConfigInfo{
Server: "numary-ledger",
Version: "latest",
Config: &controllers.Config{
LedgerStorage: &controllers.LedgerStorage{
Driver: "sqlite",
Ledgers: []string{"quickstart"},
Driver: driver.Name(),
Ledgers: []string{},
},
},
}, info)
Expand Down
12 changes: 9 additions & 3 deletions pkg/api/controllers/mapping_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,20 @@ func TestMapping(t *testing.T) {
},
}
rsp := internal.SaveMapping(t, h, m)
assert.Equal(t, http.StatusOK, rsp.Result().StatusCode)
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}

rsp = internal.LoadMapping(h)
assert.Equal(t, http.StatusOK, rsp.Result().StatusCode)
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}
m2 := core.Mapping{}
internal.DecodeSingleResponse(t, rsp.Body, &m2)

assert.EqualValues(t, m, m2)
if !assert.EqualValues(t, m, m2) {
return nil
}
return nil
},
})
Expand Down
15 changes: 15 additions & 0 deletions pkg/api/controllers/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ paths:
description: pagination cursor, will return accounts after given address (in descending order)
schema:
type: string
- name: address
in: query
description: account address
required: false
schema:
type: string
- name: metadata
in: query
description: account address
required: false
style: deepObject
schema:
type: object
additionalProperties:
type: string
responses:
"200":
description: OK
Expand Down
22 changes: 16 additions & 6 deletions pkg/api/controllers/transaction_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,29 +309,39 @@ func TestPostTransactionMetadata(t *testing.T) {
},
},
})
assert.Equal(t, http.StatusOK, rsp.Result().StatusCode)
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}
tx := make([]core.Transaction, 0)
internal.DecodeSingleResponse(t, rsp.Body, &tx)

rsp = internal.PostTransactionMetadata(t, api, tx[0].ID, core.Metadata{
"foo": json.RawMessage(`"bar"`),
})
assert.Equal(t, http.StatusNoContent, rsp.Result().StatusCode)
if !assert.Equal(t, http.StatusNoContent, rsp.Result().StatusCode) {
return nil
}

rsp = internal.GetTransaction(api, tx[0].ID)
assert.Equal(t, http.StatusOK, rsp.Result().StatusCode)
if !assert.Equal(t, http.StatusOK, rsp.Result().StatusCode) {
return nil
}

ret := core.Transaction{}
internal.DecodeSingleResponse(t, rsp.Body, &ret)

assert.EqualValues(t, core.Metadata{
if !assert.EqualValues(t, core.Metadata{
"foo": json.RawMessage(`"bar"`),
}, ret.Metadata)
}, ret.Metadata) {
return nil
}

rsp = internal.PostTransactionMetadata(t, api, tx[0].ID, core.Metadata{
"foo": json.RawMessage(`"baz"`),
})
assert.Equal(t, http.StatusNoContent, rsp.Result().StatusCode)
if !assert.Equal(t, http.StatusNoContent, rsp.Result().StatusCode) {
return nil
}
return nil
},
})
Expand Down
Loading

0 comments on commit 68b417c

Please sign in to comment.