From e0171bcbdb8adaab1172c677fe299e782e02a2cc Mon Sep 17 00:00:00 2001 From: Simon Esposito Date: Wed, 6 Sep 2023 18:10:13 +0100 Subject: [PATCH 1/5] Add storage index support for index only listings. --- go.mod | 2 ++ server/api_test.go | 4 ++-- server/storage_index.go | 2 ++ server/storage_index_test.go | 9 +++++---- vendor/modules.txt | 5 +++++ 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index c8797ebed1..6d82c083fd 100644 --- a/go.mod +++ b/go.mod @@ -81,3 +81,5 @@ require ( google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect ) + +replace github.com/heroiclabs/nakama-common => ../nakama-common diff --git a/server/api_test.go b/server/api_test.go index 66bdd02d0e..e156315d26 100644 --- a/server/api_test.go +++ b/server/api_test.go @@ -150,8 +150,8 @@ func NewConsoleLogger(output *os.File, verbose bool) *zap.Logger { } func NewDB(t *testing.T) *sql.DB { - db, err := sql.Open("pgx", "postgresql://root@127.0.0.1:26257/nakama?sslmode=disable") - //db, err := sql.Open("pgx", "postgresql://postgres@127.0.0.1:5432/nakama?sslmode=disable") + // db, err := sql.Open("pgx", "postgresql://root@127.0.0.1:26257/nakama?sslmode=disable") + db, err := sql.Open("pgx", "postgresql://postgres:postgres@127.0.0.1:5432/nakama?sslmode=disable") if err != nil { t.Fatal("Error connecting to database", err) } diff --git a/server/storage_index.go b/server/storage_index.go index a41f080be8..4e3188b592 100644 --- a/server/storage_index.go +++ b/server/storage_index.go @@ -22,6 +22,8 @@ import ( "fmt" "time" + "google.golang.org/protobuf/types/known/timestamppb" + "github.com/blugelabs/bluge" "github.com/blugelabs/bluge/index" "github.com/blugelabs/bluge/search" diff --git a/server/storage_index_test.go b/server/storage_index_test.go index b3deb017d4..7459eb9280 100644 --- a/server/storage_index_test.go +++ b/server/storage_index_test.go @@ -3,14 +3,15 @@ package server import ( "context" "encoding/json" - "github.com/gofrs/uuid/v5" - "github.com/heroiclabs/nakama-common/api" - "github.com/stretchr/testify/assert" - "google.golang.org/protobuf/types/known/timestamppb" "strings" "sync" "testing" "time" + + "github.com/gofrs/uuid/v5" + "github.com/heroiclabs/nakama-common/api" + "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/types/known/timestamppb" ) func TestLocalStorageIndex_Write(t *testing.T) { diff --git a/vendor/modules.txt b/vendor/modules.txt index ce8d58adf9..6cd178c530 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -151,7 +151,11 @@ github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopena github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options github.com/grpc-ecosystem/grpc-gateway/v2/runtime github.com/grpc-ecosystem/grpc-gateway/v2/utilities +<<<<<<< HEAD # github.com/heroiclabs/nakama-common v1.28.2-0.20231010141902-2a5051b58ac5 +======= +# github.com/heroiclabs/nakama-common v1.28.1 => ../nakama-common +>>>>>>> c0fb6089 (Add storage index support for index only listings.) ## explicit; go 1.19 github.com/heroiclabs/nakama-common/api github.com/heroiclabs/nakama-common/rtapi @@ -435,3 +439,4 @@ gopkg.in/natefinch/lumberjack.v2 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 +# github.com/heroiclabs/nakama-common => ../nakama-common From f33a6612c86b81d52fe1676a95d1af313aff5c05 Mon Sep 17 00:00:00 2001 From: Simon Esposito Date: Wed, 6 Sep 2023 18:17:09 +0100 Subject: [PATCH 2/5] Update changelog --- server/api_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/api_test.go b/server/api_test.go index e156315d26..66bdd02d0e 100644 --- a/server/api_test.go +++ b/server/api_test.go @@ -150,8 +150,8 @@ func NewConsoleLogger(output *os.File, verbose bool) *zap.Logger { } func NewDB(t *testing.T) *sql.DB { - // db, err := sql.Open("pgx", "postgresql://root@127.0.0.1:26257/nakama?sslmode=disable") - db, err := sql.Open("pgx", "postgresql://postgres:postgres@127.0.0.1:5432/nakama?sslmode=disable") + db, err := sql.Open("pgx", "postgresql://root@127.0.0.1:26257/nakama?sslmode=disable") + //db, err := sql.Open("pgx", "postgresql://postgres@127.0.0.1:5432/nakama?sslmode=disable") if err != nil { t.Fatal("Error connecting to database", err) } From f061a562e196fa03193eb26b8d6aa64e7477054e Mon Sep 17 00:00:00 2001 From: Simon Esposito Date: Fri, 8 Sep 2023 16:54:15 +0100 Subject: [PATCH 3/5] Add storageList caller id param --- server/runtime_go_nakama.go | 44 +++++++++++++++---- server/runtime_javascript_nakama.go | 29 +++++++++++- server/runtime_lua_nakama.go | 39 ++++++++++++---- server/storage_index.go | 10 +++-- .../nakama-common/runtime/runtime.go | 4 +- 5 files changed, 102 insertions(+), 24 deletions(-) diff --git a/server/runtime_go_nakama.go b/server/runtime_go_nakama.go index f0dce4f7bf..f3f4579af9 100644 --- a/server/runtime_go_nakama.go +++ b/server/runtime_go_nakama.go @@ -1867,6 +1867,7 @@ func (n *RuntimeGoNakamaModule) WalletLedgerList(ctx context.Context, userID str // @group storage // @summary List records in a collection and page through results. The records returned can be filtered to those owned by the user or "" for public records. // @param ctx(type=context.Context) The context object represents information about the server and requester. +// @param callerId(type=string) User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permissions are bypassed. // @param userId(type=string) User ID to list records for or "" (empty string) for public records. // @param collection(type=string) Collection to list data from. // @param limit(type=int, optional=true, default=100) Limit number of records retrieved. @@ -1874,7 +1875,16 @@ func (n *RuntimeGoNakamaModule) WalletLedgerList(ctx context.Context, userID str // @return objects([]*api.StorageObject) A list of storage objects. // @return cursor(string) Pagination cursor. Will be set to "" or nil when fetching last available page. // @return error(error) An optional error value if an error occurred. -func (n *RuntimeGoNakamaModule) StorageList(ctx context.Context, userID, collection string, limit int, cursor string) ([]*api.StorageObject, string, error) { +func (n *RuntimeGoNakamaModule) StorageList(ctx context.Context, callerID, userID, collection string, limit int, cursor string) ([]*api.StorageObject, string, error) { + cid := uuid.Nil + if callerID != "" { + u, err := uuid.FromString(callerID) + if err != nil { + return nil, "", errors.New("expects an empty or valid caller id") + } + cid = u + } + var uid *uuid.UUID if userID != "" { u, err := uuid.FromString(userID) @@ -1888,7 +1898,7 @@ func (n *RuntimeGoNakamaModule) StorageList(ctx context.Context, userID, collect return nil, "", errors.New("limit must not be negative") } - objectList, _, err := StorageListObjects(ctx, n.logger, n.db, uuid.Nil, uid, collection, limit, cursor) + objectList, _, err := StorageListObjects(ctx, n.logger, n.db, cid, uid, collection, limit, cursor) if err != nil { return nil, "", err } @@ -2047,19 +2057,30 @@ func (n *RuntimeGoNakamaModule) StorageDelete(ctx context.Context, deletes []*ru // @group storage // @summary List storage index entries // @param indexName(type=string) Name of the index to list entries from. +// @param callerId(type=string) User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permissions are bypassed. // @param queryString(type=string) Query to filter index entries. // @param limit(type=int) Maximum number of results to be returned. // @return objects(*api..StorageObjectList) A list of storage objects. // @return error(error) An optional error value if an error occurred. -func (n *RuntimeGoNakamaModule) StorageIndexList(ctx context.Context, indexName, query string, limit int) (*api.StorageObjects, error) { +func (n *RuntimeGoNakamaModule) StorageIndexList(ctx context.Context, callerID, indexName, query string, limit int) (*api.StorageObjects, error) { + cid := uuid.Nil + if callerID != "" { + id, err := uuid.FromString(callerID) + if err != nil { + return nil, errors.New("expects caller id to be empty or a valid user id") + } + cid = id + } + if indexName == "" { return nil, errors.New("expects a non-empty indexName") } + if limit < 1 || limit > 100 { return nil, errors.New("limit must be 1-100") } - return n.storageIndex.List(ctx, indexName, query, limit) + return n.storageIndex.List(ctx, cid, indexName, query, limit) } // @group users @@ -3297,6 +3318,7 @@ func (n *RuntimeGoNakamaModule) GroupUserLeave(ctx context.Context, groupID, use // @group groups // @summary Add users to a group. // @param ctx(type=context.Context) The context object represents information about the server and requester. +// @param callerId(type=string) User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permissions are bypassed. // @param groupId(type=string) The ID of the group to add users to. // @param userIds(type=[]string) Table array of user IDs to add to this group. // @return error(error) An optional error value if an error occurred. @@ -3305,7 +3327,7 @@ func (n *RuntimeGoNakamaModule) GroupUsersAdd(ctx context.Context, callerID, gro if callerID != "" { var err error if caller, err = uuid.FromString(callerID); err != nil { - return errors.New("expects caller ID to be a valid identifier") + return errors.New("expects caller ID to be empty or a valid identifier") } } @@ -3336,6 +3358,7 @@ func (n *RuntimeGoNakamaModule) GroupUsersAdd(ctx context.Context, callerID, gro // @group groups // @summary Ban users from a group. // @param ctx(type=context.Context) The context object represents information about the server and requester. +// @param callerId(type=string) User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permissions are bypassed. // @param groupId(type=string) The ID of the group to ban users from. // @param userIds(type=[]string) Table array of user IDs to ban from this group. // @return error(error) An optional error value if an error occurred. @@ -3344,7 +3367,7 @@ func (n *RuntimeGoNakamaModule) GroupUsersBan(ctx context.Context, callerID, gro if callerID != "" { var err error if caller, err = uuid.FromString(callerID); err != nil { - return errors.New("expects caller ID to be a valid identifier") + return errors.New("expects caller ID to be empty or a valid identifier") } } @@ -3375,6 +3398,7 @@ func (n *RuntimeGoNakamaModule) GroupUsersBan(ctx context.Context, callerID, gro // @group groups // @summary Kick users from a group. // @param ctx(type=context.Context) The context object represents information about the server and requester. +// @param callerId(type=string) User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permissions are bypassed. // @param groupId(type=string) The ID of the group to kick users from. // @param userIds(type=[]string) Table array of user IDs to kick. // @return error(error) An optional error value if an error occurred. @@ -3383,7 +3407,7 @@ func (n *RuntimeGoNakamaModule) GroupUsersKick(ctx context.Context, callerID, gr if callerID != "" { var err error if caller, err = uuid.FromString(callerID); err != nil { - return errors.New("expects caller ID to be a valid identifier") + return errors.New("expects caller ID to be empty or a valid identifier") } } @@ -3414,6 +3438,7 @@ func (n *RuntimeGoNakamaModule) GroupUsersKick(ctx context.Context, callerID, gr // @group groups // @summary Promote users in a group. // @param ctx(type=context.Context) The context object represents information about the server and requester. +// @param callerId(type=string) User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permissions are bypassed. // @param groupId(type=string) The ID of the group whose members are being promoted. // @param userIds(type=[]string) Table array of user IDs to promote. // @return error(error) An optional error value if an error occurred. @@ -3422,7 +3447,7 @@ func (n *RuntimeGoNakamaModule) GroupUsersPromote(ctx context.Context, callerID, if callerID != "" { var err error if caller, err = uuid.FromString(callerID); err != nil { - return errors.New("expects caller ID to be a valid identifier") + return errors.New("expects caller ID to be empty or a valid identifier") } } @@ -3453,6 +3478,7 @@ func (n *RuntimeGoNakamaModule) GroupUsersPromote(ctx context.Context, callerID, // @group groups // @summary Demote users in a group. // @param ctx(type=context.Context) The context object represents information about the server and requester. +// @param callerId(type=string) User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permissions are bypassed. // @param groupId(type=string) The ID of the group whose members are being demoted. // @param userIds(type=[]string) Table array of user IDs to demote. // @return error(error) An optional error value if an error occurred. @@ -3461,7 +3487,7 @@ func (n *RuntimeGoNakamaModule) GroupUsersDemote(ctx context.Context, callerID, if callerID != "" { var err error if caller, err = uuid.FromString(callerID); err != nil { - return errors.New("expects caller ID to be a valid identifier") + return errors.New("expects caller ID to be empty or a valid identifier") } } diff --git a/server/runtime_javascript_nakama.go b/server/runtime_javascript_nakama.go index fae4afa759..5f967f22f2 100644 --- a/server/runtime_javascript_nakama.go +++ b/server/runtime_javascript_nakama.go @@ -345,6 +345,7 @@ func (n *runtimeJavascriptNakamaModule) stringToBinary(r *goja.Runtime) func(goj // @param indexName(type=string) Name of the index to list entries from. // @param queryString(type=string) Query to filter index entries. // @param limit(type=int) Maximum number of results to be returned. +// @param callerId(type=string) Optional User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permission checks are bypassed. // @return objects(nkruntime.StorageObjectList) A list of storage objects. // @return error(error) An optional error value if an error occurred. func (n *runtimeJavascriptNakamaModule) storageIndexList(r *goja.Runtime) func(goja.FunctionCall) goja.Value { @@ -358,8 +359,17 @@ func (n *runtimeJavascriptNakamaModule) storageIndexList(r *goja.Runtime) func(g panic(r.NewTypeError("limit must be 1-100")) } } + callerID := uuid.Nil + if !goja.IsUndefined(f.Argument(3)) && !goja.IsNull(f.Argument(3)) { + callerIdStr := getJsString(r, f.Argument(3)) + cid, err := uuid.FromString(callerIdStr) + if err != nil { + panic(r.NewTypeError("expects caller id to be valid identifier")) + } + callerID = cid + } - objectList, err := n.storageIndex.List(n.ctx, idxName, queryString, int(limit)) + objectList, err := n.storageIndex.List(n.ctx, callerID, idxName, queryString, int(limit)) if err != nil { panic(r.NewGoError(fmt.Errorf("failed to lookup storage index: %s", err.Error()))) } @@ -4248,7 +4258,17 @@ func (n *runtimeJavascriptNakamaModule) storageList(r *goja.Runtime) func(goja.F cursor = getJsString(r, f.Argument(3)) } - objectList, _, err := StorageListObjects(n.ctx, n.logger, n.db, uuid.Nil, uid, collection, limit, cursor) + callerID := uuid.Nil + if !goja.IsUndefined(f.Argument(4)) && !goja.IsNull(f.Argument(4)) { + callerIdStr := getJsString(r, f.Argument(4)) + cid, err := uuid.FromString(callerIdStr) + if err != nil { + panic(r.NewTypeError("expects caller id to be valid identifier")) + } + callerID = cid + } + + objectList, _, err := StorageListObjects(n.ctx, n.logger, n.db, callerID, uid, collection, limit, cursor) if err != nil { panic(r.NewGoError(fmt.Errorf("failed to list storage objects: %s", err.Error()))) } @@ -6771,6 +6791,7 @@ func (n *runtimeJavascriptNakamaModule) groupDelete(r *goja.Runtime) func(goja.F // @summary Kick users from a group. // @param groupId(type=string) The ID of the group to kick users from. // @param userIds(type=string[]) Table array of user IDs to kick. +// @param callerId(type=string) Optional User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permission checks are bypassed. // @return error(error) An optional error value if an error occurred. func (n *runtimeJavascriptNakamaModule) groupUsersKick(r *goja.Runtime) func(goja.FunctionCall) goja.Value { return func(f goja.FunctionCall) goja.Value { @@ -7446,6 +7467,7 @@ func (n *runtimeJavascriptNakamaModule) groupUserLeave(r *goja.Runtime) func(goj // @summary Add users to a group. // @param groupId(type=string) The ID of the group to add users to. // @param userIds(type=string[]) Table array of user IDs to add to this group. +// @param callerId(type=string) Optional User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permission checks are bypassed. // @return error(error) An optional error value if an error occurred. func (n *runtimeJavascriptNakamaModule) groupUsersAdd(r *goja.Runtime) func(goja.FunctionCall) goja.Value { return func(f goja.FunctionCall) goja.Value { @@ -7508,6 +7530,7 @@ func (n *runtimeJavascriptNakamaModule) groupUsersAdd(r *goja.Runtime) func(goja // @summary Ban users from a group. // @param groupId(string) The ID of the group to ban users from. // @param userIds(string[]) Table array of user IDs to ban from this group. +// @param callerId(type=string) Optional User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permission checks are bypassed. // @return error(error) An optional error value if an error occurred. func (n *runtimeJavascriptNakamaModule) groupUsersBan(r *goja.Runtime) func(goja.FunctionCall) goja.Value { return func(f goja.FunctionCall) goja.Value { @@ -7570,6 +7593,7 @@ func (n *runtimeJavascriptNakamaModule) groupUsersBan(r *goja.Runtime) func(goja // @summary Promote users in a group. // @param groupId(type=string) The ID of the group whose members are being promoted. // @param userIds(type=string[]) Table array of user IDs to promote. +// @param callerId(type=string) Optional User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permission checks are bypassed. // @return error(error) An optional error value if an error occurred. func (n *runtimeJavascriptNakamaModule) groupUsersPromote(r *goja.Runtime) func(goja.FunctionCall) goja.Value { return func(f goja.FunctionCall) goja.Value { @@ -7632,6 +7656,7 @@ func (n *runtimeJavascriptNakamaModule) groupUsersPromote(r *goja.Runtime) func( // @summary Demote users in a group. // @param groupId(type=string) The ID of the group whose members are being demoted. // @param userIds(type=string[]) Table array of user IDs to demote. +// @param callerId(type=string) Optional User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permission checks are bypassed. // @return error(error) An optional error value if an error occurred. func (n *runtimeJavascriptNakamaModule) groupUsersDemote(r *goja.Runtime) func(goja.FunctionCall) goja.Value { return func(f goja.FunctionCall) goja.Value { diff --git a/server/runtime_lua_nakama.go b/server/runtime_lua_nakama.go index 66bbb16f35..c1257b1738 100644 --- a/server/runtime_lua_nakama.go +++ b/server/runtime_lua_nakama.go @@ -5539,10 +5539,11 @@ func (n *RuntimeLuaNakamaModule) walletLedgerList(l *lua.LState) int { // @group storage // @summary List records in a collection and page through results. The records returned can be filtered to those owned by the user or "" for public records. -// @param userId(type=string) User ID to list records for or "" (empty string) for public records. +// @param userId(type=string) User ID to list records for or "" (empty string) | void for public records. // @param collection(type=string) Collection to list data from. // @param limit(type=number, optional=true, default=100) Limit number of records retrieved. // @param cursor(type=string, optional=true, default="") Pagination cursor from previous result. Don't set to start fetching from the beginning. +// @param callerId(type=string, optional=true) User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permission checks are bypassed. // @return objects(table) A list of storage objects. // @return cursor(string) Pagination cursor. // @return error(error) An optional error value if an error occurred. @@ -5568,7 +5569,18 @@ func (n *RuntimeLuaNakamaModule) storageList(l *lua.LState) int { userID = &uid } - objectList, _, err := StorageListObjects(l.Context(), n.logger, n.db, uuid.Nil, userID, collection, limit, cursor) + callerID := uuid.Nil + callerIDStr := l.OptString(4, "") + if callerIDStr != "" { + cid, err := uuid.FromString(callerIDStr) + if err != nil { + l.ArgError(4, "expects caller ID to be empty or a valid identifier") + return 0 + } + callerID = cid + } + + objectList, _, err := StorageListObjects(l.Context(), n.logger, n.db, callerID, userID, collection, limit, cursor) if err != nil { l.RaiseError(fmt.Sprintf("failed to list storage objects: %s", err.Error())) return 0 @@ -8453,7 +8465,7 @@ func (n *RuntimeLuaNakamaModule) groupUsersAdd(l *lua.LState) int { if callerIDStr != "" { callerID, err = uuid.FromString(callerIDStr) if err != nil { - l.ArgError(1, "expects caller ID to be a valid identifier") + l.ArgError(3, "expects caller ID to be empty or a valid identifier") return 0 } } @@ -8516,7 +8528,7 @@ func (n *RuntimeLuaNakamaModule) groupUsersBan(l *lua.LState) int { if callerIDStr != "" { callerID, err = uuid.FromString(callerIDStr) if err != nil { - l.ArgError(1, "expects caller ID to be a valid identifier") + l.ArgError(3, "expects caller ID to be empty or a valid identifier") return 0 } } @@ -8579,7 +8591,7 @@ func (n *RuntimeLuaNakamaModule) groupUsersPromote(l *lua.LState) int { if callerIDStr != "" { callerID, err = uuid.FromString(callerIDStr) if err != nil { - l.ArgError(1, "expects caller ID to be a valid identifier") + l.ArgError(3, "expects caller ID to be empty or a valid identifier") return 0 } } @@ -8642,7 +8654,7 @@ func (n *RuntimeLuaNakamaModule) groupUsersDemote(l *lua.LState) int { if callerIDStr != "" { callerID, err = uuid.FromString(callerIDStr) if err != nil { - l.ArgError(1, "expects caller ID to be a valid identifier") + l.ArgError(3, "expects caller ID to be empty or a valid identifier") return 0 } } @@ -8705,7 +8717,7 @@ func (n *RuntimeLuaNakamaModule) groupUsersKick(l *lua.LState) int { if callerIDStr != "" { callerID, err = uuid.FromString(callerIDStr) if err != nil { - l.ArgError(1, "expects caller ID to be a valid identifier") + l.ArgError(3, "expects caller ID to be empty or a valid identifier") return 0 } } @@ -9834,6 +9846,7 @@ func (n *RuntimeLuaNakamaModule) channelIdBuild(l *lua.LState) int { // @param indexName(type=string) Name of the index to list entries from. // @param queryString(type=string) Query to filter index entries. // @param limit(type=int) Maximum number of results to be returned. +// @param callerId(type=string) Optional User ID of the caller, will apply permissions checks of the user. If empty defaults to system user and permission checks are bypassed. // @return objects(table) A list of storage objects. // @return error(error) An optional error value if an error occurred. func (n *RuntimeLuaNakamaModule) storageIndexList(l *lua.LState) int { @@ -9844,8 +9857,18 @@ func (n *RuntimeLuaNakamaModule) storageIndexList(l *lua.LState) int { l.ArgError(3, "invalid limit: expects value 1-100") return 0 } + callerID := uuid.Nil + callerIDStr := l.OptString(4, "") + if callerIDStr != "" { + cid, err := uuid.FromString(callerIDStr) + if err != nil { + l.ArgError(4, "expects caller ID to be empty or a valid identifier") + return 0 + } + callerID = cid + } - objectList, err := n.storageIndex.List(l.Context(), idxName, queryString, limit) + objectList, err := n.storageIndex.List(l.Context(), callerID, idxName, queryString, limit) if err != nil { l.RaiseError(err.Error()) return 0 diff --git a/server/storage_index.go b/server/storage_index.go index 4e3188b592..fc9b7ce8e3 100644 --- a/server/storage_index.go +++ b/server/storage_index.go @@ -37,7 +37,7 @@ import ( type StorageIndex interface { Write(ctx context.Context, objects []*api.StorageObject) (creates int, deletes int) Delete(ctx context.Context, objects StorageOpDeletes) (deletes int) - List(ctx context.Context, indexName, query string, limit int) (*api.StorageObjects, error) + List(ctx context.Context, callerID uuid.UUID, indexName, query string, limit int) (*api.StorageObjects, error) Load(ctx context.Context) error CreateIndex(ctx context.Context, name, collection, key string, fields []string, maxEntries int, indexOnly bool) error RegisterFilters(runtime *Runtime) @@ -215,7 +215,7 @@ func (si *LocalStorageIndex) Delete(ctx context.Context, objects StorageOpDelete return deletes } -func (si *LocalStorageIndex) List(ctx context.Context, indexName, query string, limit int) (*api.StorageObjects, error) { +func (si *LocalStorageIndex) List(ctx context.Context, callerID uuid.UUID, indexName, query string, limit int) (*api.StorageObjects, error) { idx, found := si.indexByName[indexName] if !found { return nil, fmt.Errorf("index %q not found", indexName) @@ -257,6 +257,10 @@ func (si *LocalStorageIndex) List(ctx context.Context, indexName, query string, if !si.config.DisableIndexOnly && idx.IndexOnly { objects := make([]*api.StorageObject, 0, len(indexResults)) for _, idxResult := range indexResults { + if callerID != uuid.Nil && !(idxResult.Read == 2 || idxResult.UserID == callerID.String()) { + continue + } + objects = append(objects, &api.StorageObject{ Collection: idxResult.Collection, Key: idxResult.Key, @@ -282,7 +286,7 @@ func (si *LocalStorageIndex) List(ctx context.Context, indexName, query string, }) } - objects, err := StorageReadObjects(ctx, si.logger, si.db, uuid.Nil, storageReads) + objects, err := StorageReadObjects(ctx, si.logger, si.db, callerID, storageReads) if err != nil { return nil, err } diff --git a/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go b/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go index acd2b02f8f..c0db3a734f 100644 --- a/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go +++ b/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go @@ -1066,11 +1066,11 @@ type NakamaModule interface { WalletLedgerUpdate(ctx context.Context, itemID string, metadata map[string]interface{}) (WalletLedgerItem, error) WalletLedgerList(ctx context.Context, userID string, limit int, cursor string) ([]WalletLedgerItem, string, error) - StorageList(ctx context.Context, userID, collection string, limit int, cursor string) ([]*api.StorageObject, string, error) + StorageList(ctx context.Context, callerID, userID, collection string, limit int, cursor string) ([]*api.StorageObject, string, error) StorageRead(ctx context.Context, reads []*StorageRead) ([]*api.StorageObject, error) StorageWrite(ctx context.Context, writes []*StorageWrite) ([]*api.StorageObjectAck, error) StorageDelete(ctx context.Context, deletes []*StorageDelete) error - StorageIndexList(ctx context.Context, indexName, query string, limit int) (*api.StorageObjects, error) + StorageIndexList(ctx context.Context, callerID, indexName, query string, limit int) (*api.StorageObjects, error) MultiUpdate(ctx context.Context, accountUpdates []*AccountUpdate, storageWrites []*StorageWrite, walletUpdates []*WalletUpdate, updateLedger bool) ([]*api.StorageObjectAck, []*WalletUpdateResult, error) From 8cc003676e1e6516633526c9e097e9a39932a24c Mon Sep 17 00:00:00 2001 From: Simon Esposito Date: Tue, 10 Oct 2023 17:17:58 +0100 Subject: [PATCH 4/5] Review changes --- go.mod | 4 +--- go.sum | 4 ++-- server/storage_index.go | 3 +-- server/storage_index_test.go | 16 ++++++++-------- vendor/modules.txt | 7 +------ 5 files changed, 13 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 6d82c083fd..c613775d33 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/gorilla/websocket v1.5.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 - github.com/heroiclabs/nakama-common v1.28.2-0.20231010141902-2a5051b58ac5 + github.com/heroiclabs/nakama-common v1.28.2-0.20231010150216-b178843845fa github.com/jackc/pgconn v1.14.0 github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa github.com/jackc/pgtype v1.14.0 @@ -81,5 +81,3 @@ require ( google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect ) - -replace github.com/heroiclabs/nakama-common => ../nakama-common diff --git a/go.sum b/go.sum index 1f14799510..f0762b765d 100644 --- a/go.sum +++ b/go.sum @@ -292,8 +292,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/heroiclabs/nakama-common v1.28.2-0.20231010141902-2a5051b58ac5 h1:AbvTXur7NgDz6j9JLMgsVoW1ifJpR+/5F2W2omjdbL4= -github.com/heroiclabs/nakama-common v1.28.2-0.20231010141902-2a5051b58ac5/go.mod h1:Os8XeXGvHAap/p6M/8fQ3gle4eEXDGRQmoRNcPQTjXs= +github.com/heroiclabs/nakama-common v1.28.2-0.20231010150216-b178843845fa h1:2yXME7CoepD1WIV/iGpMOVmyhFxlTrM4dGTKBxqaLpw= +github.com/heroiclabs/nakama-common v1.28.2-0.20231010150216-b178843845fa/go.mod h1:Os8XeXGvHAap/p6M/8fQ3gle4eEXDGRQmoRNcPQTjXs= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= diff --git a/server/storage_index.go b/server/storage_index.go index fc9b7ce8e3..4b9e3f8dd6 100644 --- a/server/storage_index.go +++ b/server/storage_index.go @@ -22,8 +22,6 @@ import ( "fmt" "time" - "google.golang.org/protobuf/types/known/timestamppb" - "github.com/blugelabs/bluge" "github.com/blugelabs/bluge/index" "github.com/blugelabs/bluge/search" @@ -228,6 +226,7 @@ func (si *LocalStorageIndex) List(ctx context.Context, callerID uuid.UUID, index if query == "" { query = "*" } + parsedQuery, err := ParseQueryString(query) if err != nil { return nil, err diff --git a/server/storage_index_test.go b/server/storage_index_test.go index 7459eb9280..a651eb9ccb 100644 --- a/server/storage_index_test.go +++ b/server/storage_index_test.go @@ -125,13 +125,13 @@ func TestLocalStorageIndex_Write(t *testing.T) { t.Fatal(err.Error()) } - entries, err := storageIdx.List(ctx, indexName1, "", maxEntries1) // Match all + entries, err := storageIdx.List(ctx, uuid.Nil, indexName1, "", maxEntries1) // Match all if err != nil { t.Fatal(err.Error()) } assert.Len(t, entries.Objects, 2, "indexed results length was not 2") - entries, err = storageIdx.List(ctx, indexName2, "", maxEntries1) // Match all + entries, err = storageIdx.List(ctx, uuid.Nil, indexName2, "", maxEntries1) // Match all if err != nil { t.Fatal(err.Error()) } @@ -172,7 +172,7 @@ func TestLocalStorageIndex_Write(t *testing.T) { t.Fatal(err.Error()) } - entries, err := storageIdx.List(ctx, indexName1, "+value.three:3", maxEntries1) + entries, err := storageIdx.List(ctx, uuid.Nil, indexName1, "+value.three:3", maxEntries1) if err != nil { t.Fatal(err.Error()) } @@ -275,7 +275,7 @@ func TestLocalStorageIndex_Write(t *testing.T) { t.Fatal(err.Error()) } - entries, err := storageIdx.List(ctx, indexName2, "", maxEntries2) + entries, err := storageIdx.List(ctx, uuid.Nil, indexName2, "", maxEntries2) if err != nil { t.Fatal(err.Error()) } @@ -371,7 +371,7 @@ func TestLocalStorageIndex_List(t *testing.T) { t.Fatal(err.Error()) } - entries, err := storageIdx.List(ctx, indexName, "value.one:1 value.three:3", 10) + entries, err := storageIdx.List(ctx, uuid.Nil, indexName, "value.one:1 value.three:3", 10) if err != nil { t.Fatal(err.Error()) } @@ -464,7 +464,7 @@ func TestLocalStorageIndex_List(t *testing.T) { t.Fatal(err.Error()) } - entries, err := storageIdx.List(ctx, indexName, "value.one:1 value.three:3", 10) + entries, err := storageIdx.List(ctx, uuid.Nil, indexName, "value.one:1 value.three:3", 10) if err != nil { t.Fatal(err.Error()) } @@ -540,7 +540,7 @@ func TestLocalStorageIndex_Delete(t *testing.T) { t.Fatal(err.Error()) } - entries, err := storageIdx.List(ctx, indexName, "", 10) + entries, err := storageIdx.List(ctx, uuid.Nil, indexName, "", 10) if err != nil { t.Fatal(err.Error()) } @@ -557,7 +557,7 @@ func TestLocalStorageIndex_Delete(t *testing.T) { t.Fatal(err.Error()) } - entries, err = storageIdx.List(ctx, indexName, "", 10) + entries, err = storageIdx.List(ctx, uuid.Nil, indexName, "", 10) if err != nil { t.Fatal(err.Error()) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 6cd178c530..a7d7dfb085 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -151,11 +151,7 @@ github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopena github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options github.com/grpc-ecosystem/grpc-gateway/v2/runtime github.com/grpc-ecosystem/grpc-gateway/v2/utilities -<<<<<<< HEAD -# github.com/heroiclabs/nakama-common v1.28.2-0.20231010141902-2a5051b58ac5 -======= -# github.com/heroiclabs/nakama-common v1.28.1 => ../nakama-common ->>>>>>> c0fb6089 (Add storage index support for index only listings.) +# github.com/heroiclabs/nakama-common v1.28.2-0.20231010150216-b178843845fa ## explicit; go 1.19 github.com/heroiclabs/nakama-common/api github.com/heroiclabs/nakama-common/rtapi @@ -439,4 +435,3 @@ gopkg.in/natefinch/lumberjack.v2 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 -# github.com/heroiclabs/nakama-common => ../nakama-common From 81ecbaa6ca9f1195544675e54ad03da71f1a0273 Mon Sep 17 00:00:00 2001 From: Simon Esposito Date: Fri, 13 Oct 2023 12:02:15 +0100 Subject: [PATCH 5/5] Update changelog --- CHANGELOG.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5288b3b2d4..a2228ecac7 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,16 +6,13 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr ## [Unreleased] ### Changed - Use Steam partner API instead of public API for Steam profiles and friends requests. - -### Fixed -- Fix linter-found test issue. -- Fix storage index listing results sometimes being returned with incorrect order. - -### Changed - Add create_time and update_time to returned storage engine writes acks. - Add storage index create flag to read only from the index. +- Add caller id param to storage listing and storage index listing runtime APIs. ### Fixed +- Fix linter-found test issue. +- Fix storage index listing results sometimes being returned with incorrect order. - Fixes calculation of leaderboard and tournament times for rare types of CRON expressions that don't execute at a fixed interval. - Improved how start and end times are calculated for tournaments occuring in the future.