diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e2b3060069c694d080f6d8bfab2d8a54364f4bd..80f1bcd9268cc0f66ce52f7692572bd18c9e1d6a 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr - Added JavaScript runtime function to clear all localcache data. - Added support for per-key TTL in Lua runtime localcache. - Added support for per-key TTL in JavaScript runtime localcache. +- Add support for optional client IP address passthrough to runtime Satori client. ### Changed - Remove unused config 'matchmaker.batch_pool_size'. diff --git a/go.mod b/go.mod index d73729a52d8f155cdad70d0173d2350decf81617..d9c164d3172424909fe19800974f967e3cbf4ec0 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,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 v0.0.0-20231110231506-a6d791dbc20f + github.com/heroiclabs/nakama-common v0.0.0-20231111182915-5206c3ece9b0 github.com/jackc/pgconn v1.14.0 github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa github.com/jackc/pgtype v1.14.0 diff --git a/go.sum b/go.sum index f5c0b02ec3f179f00b1a08b1ae32a492ac4dd968..2c6c9a82f484a1036a6b6c731f80e846981b75e3 100644 --- a/go.sum +++ b/go.sum @@ -302,8 +302,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 v0.0.0-20231110231506-a6d791dbc20f h1:sthlTetnKYxex7iS4BgW5S49s5zqPtBzg2XN1NPfvq0= -github.com/heroiclabs/nakama-common v0.0.0-20231110231506-a6d791dbc20f/go.mod h1:Os8XeXGvHAap/p6M/8fQ3gle4eEXDGRQmoRNcPQTjXs= +github.com/heroiclabs/nakama-common v0.0.0-20231111182915-5206c3ece9b0 h1:iGR26K0+AIhf5pJuRsDeDxTt6BeVJfyv6ys94xgiEnY= +github.com/heroiclabs/nakama-common v0.0.0-20231111182915-5206c3ece9b0/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/internal/satori/satori.go b/internal/satori/satori.go index 3781a96d3b9778b9e8addb5b4aeb50f9e3f2b666..594a175127a8ff7c8f050b1090c97b7f8a8dd95c 100644 --- a/internal/satori/satori.go +++ b/internal/satori/satori.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "io" + "net" "net/http" "net/url" "strings" @@ -141,8 +142,9 @@ type authenticateBody struct { // @summary Create a new identity. // @param ctx(type=context.Context) The context object represents information about the server and requester. // @param id(type=string) The identifier of the identity. +// @param ipAddress(type=string, optional=true) An optional client IP address to pass on to Satori for geo-IP lookup. // @return error(error) An optional error value if an error occurred. -func (s *SatoriClient) Authenticate(ctx context.Context, id string) error { +func (s *SatoriClient) Authenticate(ctx context.Context, id string, ipAddress ...string) error { if s.invalidConfig { return runtime.ErrSatoriConfigurationInvalid } @@ -162,6 +164,13 @@ func (s *SatoriClient) Authenticate(ctx context.Context, id string) error { } req.Header.Set("Content-Type", "application/json") req.SetBasicAuth(s.apiKey, "") + if len(ipAddress) > 0 && ipAddress[0] != "" { + if ipAddr := net.ParseIP(ipAddress[0]); ipAddr != nil { + req.Header.Set("X-Forwarded-For", ipAddr.String()) + } + } else if ipAddr, ok := ctx.Value(runtime.RUNTIME_CTX_CLIENT_IP).(string); ok { + req.Header.Set("X-Forwarded-For", ipAddr) + } res, err := s.httpc.Do(req) if err != nil { diff --git a/server/api_test.go b/server/api_test.go index 8ce8961ab76e930b85aa36c2eb4a2225759f8696..90503e7b881d48e6cd2841e61abf9523dad3fc38 100644 --- a/server/api_test.go +++ b/server/api_test.go @@ -53,7 +53,7 @@ var ( DiscardUnknown: false, } metrics = NewLocalMetrics(logger, logger, nil, cfg) - storageIdx, _ = NewLocalStorageIndex(logger, nil, &StorageConfig{DisableIndexOnly: false}) + storageIdx, _ = NewLocalStorageIndex(logger, nil, &StorageConfig{DisableIndexOnly: false}, metrics) _ = CheckConfig(logger, cfg) ) diff --git a/server/match_common_test.go b/server/match_common_test.go index 91689eea70f0eb1fa851ff8daffc00d1f8f52ccc..4d6f64efa5f620d44ced4410453e48e1ab228f25 100644 --- a/server/match_common_test.go +++ b/server/match_common_test.go @@ -180,6 +180,7 @@ func (s *testMetrics) GaugeRuntimes(value float64) func (s *testMetrics) GaugeLuaRuntimes(value float64) {} func (s *testMetrics) GaugeJsRuntimes(value float64) {} func (s *testMetrics) GaugeAuthoritativeMatches(value float64) {} +func (s *testMetrics) GaugeStorageIndexEntries(indexName string, value float64) {} func (s *testMetrics) CountDroppedEvents(delta int64) {} func (s *testMetrics) CountWebsocketOpened(delta int64) {} func (s *testMetrics) CountWebsocketClosed(delta int64) {} diff --git a/server/runtime_javascript_nakama.go b/server/runtime_javascript_nakama.go index 46b569ad549226bae56806a91caab67a10553dbd..4af5af79b582d6877ccc3091c2f305ce761136eb 100644 --- a/server/runtime_javascript_nakama.go +++ b/server/runtime_javascript_nakama.go @@ -8390,7 +8390,12 @@ func (n *runtimeJavascriptNakamaModule) satoriAuthenticate(r *goja.Runtime) func return func(f goja.FunctionCall) goja.Value { id := getJsString(r, f.Argument(0)) - if err := n.satori.Authenticate(n.ctx, id); err != nil { + var ip string + if f.Argument(1) != goja.Undefined() && f.Argument(1) != goja.Null() { + ip = getJsString(r, f.Argument(1)) + } + + if err := n.satori.Authenticate(n.ctx, id, ip); err != nil { n.logger.Error("Failed to Satori Authenticate.", zap.Error(err)) panic(r.NewGoError(fmt.Errorf("failed to satori authenticate: %s", err.Error()))) } diff --git a/server/runtime_lua_nakama.go b/server/runtime_lua_nakama.go index c52975fe98f0cceb47d03b596c01434f4b25dbfa..6400c359e906ccc165fb96abec52493897225303 100644 --- a/server/runtime_lua_nakama.go +++ b/server/runtime_lua_nakama.go @@ -10058,8 +10058,9 @@ func (n *RuntimeLuaNakamaModule) getSatori(l *lua.LState) int { // @return error(error) An optional error value if an error occurred. func (n *RuntimeLuaNakamaModule) satoriAuthenticate(l *lua.LState) int { identifier := l.CheckString(1) + ip := l.OptString(2, "") - if err := n.satori.Authenticate(l.Context(), identifier); err != nil { + if err := n.satori.Authenticate(l.Context(), identifier, ip); err != nil { l.RaiseError("failed to satori authenticate: %v", err.Error()) return 0 } diff --git a/server/storage_index_test.go b/server/storage_index_test.go index a651eb9ccb1d720b8a752a85f26eacd5cbf4a55e..90c61dece92bd9a0f22580d6f1ade54db9ca06d0 100644 --- a/server/storage_index_test.go +++ b/server/storage_index_test.go @@ -55,7 +55,7 @@ func TestLocalStorageIndex_Write(t *testing.T) { }) valueThree := string(valueThreeBytes) - storageIdx, err := NewLocalStorageIndex(logger, db, &StorageConfig{}) + storageIdx, err := NewLocalStorageIndex(logger, db, &StorageConfig{}, metrics) if err != nil { t.Fatal(err.Error()) } @@ -207,7 +207,7 @@ func TestLocalStorageIndex_Write(t *testing.T) { UpdateTime: timestamppb.New(ts), } - storageIdx, err := NewLocalStorageIndex(logger, db, &StorageConfig{}) + storageIdx, err := NewLocalStorageIndex(logger, db, &StorageConfig{}, metrics) if err != nil { t.Fatal(err.Error()) } @@ -331,7 +331,7 @@ func TestLocalStorageIndex_List(t *testing.T) { }) valueThree := string(valueThreeBytes) - storageIdx, err := NewLocalStorageIndex(logger, db, &StorageConfig{}) + storageIdx, err := NewLocalStorageIndex(logger, db, &StorageConfig{}, metrics) if err != nil { t.Fatal(err.Error()) } @@ -424,7 +424,7 @@ func TestLocalStorageIndex_List(t *testing.T) { }) valueThree := string(valueThreeBytes) - storageIdx, err := NewLocalStorageIndex(logger, db, &StorageConfig{}) + storageIdx, err := NewLocalStorageIndex(logger, db, &StorageConfig{}, metrics) if err != nil { t.Fatal(err.Error()) } @@ -508,7 +508,7 @@ func TestLocalStorageIndex_Delete(t *testing.T) { }) valueOne := string(valueOneBytes) - storageIdx, err := NewLocalStorageIndex(logger, db, &StorageConfig{}) + storageIdx, err := NewLocalStorageIndex(logger, db, &StorageConfig{}, metrics) if err != nil { t.Fatal(err.Error()) } diff --git a/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go b/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go index ba5ddbf262da28fba986f46223c7a33342f73e54..5522a1bf7d437c0df2c9202b0a257e40d9b12280 100644 --- a/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go +++ b/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go @@ -1159,7 +1159,7 @@ type NakamaModule interface { Satori runtime integration defintions. */ type Satori interface { - Authenticate(ctx context.Context, id string) error + Authenticate(ctx context.Context, id string, ipAddress ...string) error PropertiesGet(ctx context.Context, id string) (*Properties, error) PropertiesUpdate(ctx context.Context, id string, properties *PropertiesUpdate) error EventsPublish(ctx context.Context, id string, events []*Event) error diff --git a/vendor/modules.txt b/vendor/modules.txt index 46346b547c73110666924da4f5fca83834c26546..faa0309ee4fe55042acd2277b4afb7d667fd9e62 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -156,7 +156,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 -# github.com/heroiclabs/nakama-common v0.0.0-20231110231506-a6d791dbc20f +# github.com/heroiclabs/nakama-common v0.0.0-20231111182915-5206c3ece9b0 ## explicit; go 1.19 github.com/heroiclabs/nakama-common/api github.com/heroiclabs/nakama-common/rtapi