From 1846b7c6cc816ce363a41391f03004efe64b1101 Mon Sep 17 00:00:00 2001 From: Francesco Ilario Date: Thu, 25 Jul 2024 14:53:27 +0200 Subject: [PATCH 1/3] add public-viewer support to pkg/context this commit is part of PR #443 Signed-off-by: Francesco Ilario --- pkg/context/keys.go | 4 +++ pkg/context/public_viewer.go | 12 +++++++ pkg/context/public_viewer_test.go | 53 +++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 pkg/context/public_viewer.go create mode 100644 pkg/context/public_viewer_test.go diff --git a/pkg/context/keys.go b/pkg/context/keys.go index 9477de21..a6eba535 100644 --- a/pkg/context/keys.go +++ b/pkg/context/keys.go @@ -25,4 +25,8 @@ const ( WorkspaceKey = "workspace" // RequestReceivedTime is the context key for the starting time of a request made RequestReceivedTime = "requestReceivedTime" + // PublicViewerEnabled is a boolean value indicating whether PublicViewer support is enabled + PublicViewerEnabled = "publicViewerEnabled" + // ImpersonateUser is the context key for the impersonated user in proxied call + ImpersonateUser = "impersonateUser" ) diff --git a/pkg/context/public_viewer.go b/pkg/context/public_viewer.go new file mode 100644 index 00000000..d7f11b23 --- /dev/null +++ b/pkg/context/public_viewer.go @@ -0,0 +1,12 @@ +package context + +import ( + "github.com/labstack/echo/v4" +) + +// IsPublicViewerEnabled retrieves from the context the boolean value associated to the PublicViewerEnabled key. +// If the key is not set it returns false, otherwise it returns the boolean value stored in the context. +func IsPublicViewerEnabled(ctx echo.Context) bool { + publicViewerEnabled, _ := ctx.Get(PublicViewerEnabled).(bool) + return publicViewerEnabled +} diff --git a/pkg/context/public_viewer_test.go b/pkg/context/public_viewer_test.go new file mode 100644 index 00000000..9b86d62f --- /dev/null +++ b/pkg/context/public_viewer_test.go @@ -0,0 +1,53 @@ +package context_test + +import ( + "testing" + + "github.com/codeready-toolchain/registration-service/pkg/context" + "github.com/labstack/echo/v4" + "github.com/stretchr/testify/require" +) + +func TestIsPublicViewerEnabled(t *testing.T) { + tt := map[string]struct { + data map[string]interface{} + expected bool + }{ + "context value is true": { + data: map[string]interface{}{context.PublicViewerEnabled: true}, + expected: true, + }, + "context value is false": { + data: map[string]interface{}{context.PublicViewerEnabled: false}, + expected: false, + }, + "value not set in context": { + data: map[string]interface{}{}, + expected: false, + }, + "value set to a not castable value": { + data: map[string]interface{}{context.PublicViewerEnabled: struct{}{}}, + expected: false, + }, + "value set to nil": { + data: map[string]interface{}{context.PublicViewerEnabled: nil}, + expected: false, + }, + } + + for k, tc := range tt { + t.Run(k, func(t *testing.T) { + // given + ctx := echo.New().NewContext(nil, nil) + for k, v := range tc.data { + ctx.Set(k, v) + } + + // when + actual := context.IsPublicViewerEnabled(ctx) + + // then + require.Equal(t, tc.expected, actual, "IsPublicViewerEnabled returned a value different from expected") + }) + } +} From e1c5c9b918d88370360bf4c25bff513fd86cba68 Mon Sep 17 00:00:00 2001 From: Francesco Ilario Date: Thu, 25 Jul 2024 19:49:07 +0200 Subject: [PATCH 2/3] add public-viewer support to pkg/log this commit is part of PR #443 Signed-off-by: Francesco Ilario --- pkg/log/log.go | 8 +++++ pkg/log/log_test.go | 79 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/pkg/log/log.go b/pkg/log/log.go index f2107f8e..7ab56dee 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -149,6 +149,14 @@ func (l *Logger) InfoEchof(ctx echo.Context, msg string, args ...string) { ctxFields = append(ctxFields, "url") ctxFields = append(ctxFields, ctx.Request().URL) + if impersonateUser, ok := ctx.Get(context.ImpersonateUser).(string); ok { + ctxFields = append(ctxFields, "impersonate-user", impersonateUser) + } + + if publicViewerEnabled, ok := ctx.Get(context.PublicViewerEnabled).(bool); ok { + ctxFields = append(ctxFields, "public-viewer-enabled", publicViewerEnabled) + } + l.infof(ctxFields, msg, args...) } diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go index e251f495..9183df50 100644 --- a/pkg/log/log_test.go +++ b/pkg/log/log_test.go @@ -60,25 +60,68 @@ func TestLog(t *testing.T) { }) t.Run("log infoEchof", func(t *testing.T) { - buf.Reset() - req := httptest.NewRequest(http.MethodGet, "https://api-server.com/api/workspaces/path", strings.NewReader("{}")) - rec := httptest.NewRecorder() - ctx := echo.New().NewContext(req, rec) - ctx.Set(context.SubKey, "test") - ctx.Set(context.UsernameKey, "usernametest") - ctx.Set(context.WorkspaceKey, "coolworkspace") + tt := map[string]struct { + name string + contains string + notContains string + ctxSet map[string]interface{} + }{ + "default": {}, + "impersonateUser is set": { + ctxSet: map[string]interface{}{context.ImpersonateUser: "user"}, + contains: `"impersonate-user":"user"`, + }, + "impersonateUser is not set": { + ctxSet: map[string]interface{}{}, + notContains: `impersonate-user`, + }, + "public-viewer-enabled is set to true": { + ctxSet: map[string]interface{}{context.PublicViewerEnabled: true}, + contains: `"public-viewer-enabled":true`, + }, + "public-viewer-enabled is set to false": { + ctxSet: map[string]interface{}{context.PublicViewerEnabled: false}, + contains: `"public-viewer-enabled":false`, + }, + "public-viewer-enabled is not set": { + ctxSet: map[string]interface{}{}, + notContains: `public-viewer-enabled`, + }, + } - InfoEchof(ctx, "test %s", "info") - value := buf.String() - assert.Contains(t, value, `"logger":"logger_tests"`) - assert.Contains(t, value, `"msg":"test info"`) - assert.Contains(t, value, `"user_id":"test"`) // subject -> user_id - assert.Contains(t, value, `"username":"usernametest"`) - assert.Contains(t, value, `"level":"info"`) - assert.Contains(t, value, `"timestamp":"`) - assert.Contains(t, value, `"workspace":"coolworkspace"`) - assert.Contains(t, value, `"method":"GET"`) - assert.Contains(t, value, `"url":"https://api-server.com/api/workspaces/path"`) + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + buf.Reset() + req := httptest.NewRequest(http.MethodGet, "https://api-server.com/api/workspaces/path", strings.NewReader("{}")) + rec := httptest.NewRecorder() + ctx := echo.New().NewContext(req, rec) + ctx.Set(context.SubKey, "test") + ctx.Set(context.UsernameKey, "usernametest") + ctx.Set(context.WorkspaceKey, "coolworkspace") + for k, v := range tc.ctxSet { + ctx.Set(k, v) + } + + InfoEchof(ctx, "test %s", "info") + value := buf.String() + assert.Contains(t, value, `"logger":"logger_tests"`) + assert.Contains(t, value, `"msg":"test info"`) + assert.Contains(t, value, `"user_id":"test"`) // subject -> user_id + assert.Contains(t, value, `"username":"usernametest"`) + assert.Contains(t, value, `"level":"info"`) + assert.Contains(t, value, `"timestamp":"`) + assert.Contains(t, value, `"workspace":"coolworkspace"`) + assert.Contains(t, value, `"method":"GET"`) + assert.Contains(t, value, `"url":"https://api-server.com/api/workspaces/path"`) + + if tc.contains != "" { + assert.Contains(t, value, tc.contains) + } + if tc.notContains != "" { + assert.NotContains(t, value, tc.notContains) + } + }) + } }) t.Run("log infof with no arguments", func(t *testing.T) { From 3ff55d964d6fd3cd5d450384bad4c5a348561939 Mon Sep 17 00:00:00 2001 From: Francesco Ilario Date: Wed, 31 Jul 2024 18:47:42 +0200 Subject: [PATCH 3/3] Update pkg/log/log_test.go --- pkg/log/log_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go index 9183df50..de837486 100644 --- a/pkg/log/log_test.go +++ b/pkg/log/log_test.go @@ -67,11 +67,11 @@ func TestLog(t *testing.T) { ctxSet map[string]interface{} }{ "default": {}, - "impersonateUser is set": { + "impersonate-user is set": { ctxSet: map[string]interface{}{context.ImpersonateUser: "user"}, contains: `"impersonate-user":"user"`, }, - "impersonateUser is not set": { + "impersonate-user is not set": { ctxSet: map[string]interface{}{}, notContains: `impersonate-user`, },