diff --git a/internal/app/service/metadata/handler/http.go b/internal/app/service/metadata/handler/http.go index 0d129dc9..1873c67c 100644 --- a/internal/app/service/metadata/handler/http.go +++ b/internal/app/service/metadata/handler/http.go @@ -5,8 +5,10 @@ import ( "net/http" "proctor/internal/app/service/infra/logger" "proctor/internal/app/service/metadata/repository" + "proctor/internal/app/service/security/middleware" "proctor/internal/pkg/constant" modelMetadata "proctor/internal/pkg/model/metadata" + "proctor/pkg/auth" ) type metadataHTTPHandler struct { @@ -55,7 +57,19 @@ func (handler *metadataHTTPHandler) Post() http.HandlerFunc { func (handler *metadataHTTPHandler) GetAll() http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { - metadataSlice, err := handler.repository.GetAll() + userDetailContext := req.Context().Value(middleware.ContextUserDetailKey) + if userDetailContext == nil { + w.WriteHeader(http.StatusUnauthorized) + return + } + + userDetail, ok := userDetailContext.(*auth.UserDetail) + if !ok { + w.WriteHeader(http.StatusUnauthorized) + return + } + + metadataSlice, err := handler.repository.GetAllByGroups(userDetail.Groups) if err != nil { logger.Error("Error fetching metadata", err.Error()) diff --git a/internal/app/service/metadata/handler/http_test.go b/internal/app/service/metadata/handler/http_test.go index 2987f86c..c54e848b 100644 --- a/internal/app/service/metadata/handler/http_test.go +++ b/internal/app/service/metadata/handler/http_test.go @@ -2,12 +2,15 @@ package handler import ( "bytes" + "context" "encoding/json" "errors" "fmt" "net/http" "net/http/httptest" metadataRepository "proctor/internal/app/service/metadata/repository" + "proctor/internal/app/service/security/middleware" + "proctor/pkg/auth" "testing" "proctor/internal/pkg/model/metadata/env" @@ -121,10 +124,20 @@ func (s *MetadataHandlerTestSuite) TestHandleBulkDisplay() { t := s.T() req := httptest.NewRequest("GET", "/metadata", bytes.NewReader([]byte{})) + groups := []string{"admin", "migratior"} + userDetail := &auth.UserDetail{ + Name: "jasoet", + Email: "jasoet@ambyar.com", + Active: true, + Groups: groups, + } + + ctx := context.WithValue(req.Context(), middleware.ContextUserDetailKey, userDetail) + req = req.WithContext(ctx) responseRecorder := httptest.NewRecorder() - jobsMetadata := []modelMetadata.Metadata{} - s.mockRepository.On("GetAll").Return(jobsMetadata, nil).Once() + var jobsMetadata []modelMetadata.Metadata + s.mockRepository.On("GetAllByGroups", groups).Return(jobsMetadata, nil).Once() s.metadataHTTPHandler.GetAll()(responseRecorder, req) @@ -141,10 +154,20 @@ func (s *MetadataHandlerTestSuite) TestHandleBulkDisplayStoreFailure() { t := s.T() req := httptest.NewRequest("GET", "/metadata", bytes.NewReader([]byte{})) + groups := []string{"admin", "migratior"} + userDetail := &auth.UserDetail{ + Name: "jasoet", + Email: "jasoet@ambyar.com", + Active: true, + Groups: groups, + } + + ctx := context.WithValue(req.Context(), middleware.ContextUserDetailKey, userDetail) + req = req.WithContext(ctx) responseRecorder := httptest.NewRecorder() jobsMetadata := []modelMetadata.Metadata{} - s.mockRepository.On("GetAll").Return(jobsMetadata, errors.New("error")).Once() + s.mockRepository.On("GetAllByGroups", groups).Return(jobsMetadata, errors.New("error")).Once() s.metadataHTTPHandler.GetAll()(responseRecorder, req) diff --git a/internal/app/service/metadata/repository/metadata.go b/internal/app/service/metadata/repository/metadata.go index d2e57abe..2cca83ee 100644 --- a/internal/app/service/metadata/repository/metadata.go +++ b/internal/app/service/metadata/repository/metadata.go @@ -11,6 +11,7 @@ const KeySuffix = "-metadata" type MetadataRepository interface { Save(metadata metadata.Metadata) error GetAll() ([]metadata.Metadata, error) + GetAllByGroups(groups []string) ([]metadata.Metadata, error) GetByName(name string) (*metadata.Metadata, error) } @@ -68,6 +69,55 @@ func (repository *metadataRepository) GetAll() ([]metadata.Metadata, error) { return metadataSlice, nil } +func (repository *metadataRepository) GetAllByGroups(groups []string) ([]metadata.Metadata, error) { + searchKey := "*" + KeySuffix + + keys, err := repository.redisClient.KEYS(searchKey) + if err != nil { + return nil, err + } + + availableKeys := make([]interface{}, len(keys)) + for i := range keys { + availableKeys[i] = keys[i] + } + + values, err := repository.redisClient.MGET(availableKeys...) + if err != nil { + return nil, err + } + + metadataSlice := make([]metadata.Metadata, len(values)) + for i := range values { + err = json.Unmarshal(values[i], &metadataSlice[i]) + if err != nil { + return nil, err + } + } + + var filteredMetadata []metadata.Metadata + for _, meta := range metadataSlice { + if len(meta.AuthorizedGroups) == 0 { + filteredMetadata = append(filteredMetadata, meta) + } else if duplicateItemExists(meta.AuthorizedGroups, groups) { + filteredMetadata = append(filteredMetadata, meta) + } + } + + return filteredMetadata, nil +} + +func duplicateItemExists(first []string, second []string) bool { + for _, firstString := range first { + for _, secondString := range second { + if firstString == secondString { + return true + } + } + } + return false +} + func (repository *metadataRepository) GetByName(name string) (*metadata.Metadata, error) { binaryMetadata, err := repository.redisClient.GET(applySuffix(name)) if err != nil { diff --git a/internal/app/service/metadata/repository/metadata_mock.go b/internal/app/service/metadata/repository/metadata_mock.go index 459d3965..65252887 100644 --- a/internal/app/service/metadata/repository/metadata_mock.go +++ b/internal/app/service/metadata/repository/metadata_mock.go @@ -19,6 +19,11 @@ func (m *MockMetadataRepository) GetAll() ([]modelMetadata.Metadata, error) { return args.Get(0).([]modelMetadata.Metadata), args.Error(1) } +func (m *MockMetadataRepository) GetAllByGroups(group []string) ([]modelMetadata.Metadata, error) { + args := m.Called(group) + return args.Get(0).([]modelMetadata.Metadata), args.Error(1) +} + func (m *MockMetadataRepository) GetByName(name string) (*modelMetadata.Metadata, error) { args := m.Called(name) return args.Get(0).(*modelMetadata.Metadata), args.Error(1) diff --git a/internal/app/service/metadata/repository/metadata_test.go b/internal/app/service/metadata/repository/metadata_test.go index 08e288b1..bc0fdab9 100644 --- a/internal/app/service/metadata/repository/metadata_test.go +++ b/internal/app/service/metadata/repository/metadata_test.go @@ -113,6 +113,84 @@ func (s *MetadataRepositoryTestSuite) TestGetAllFailure() { s.mockRedisClient.AssertExpectations(t) } +func (s *MetadataRepositoryTestSuite) TestGetAllByGroups() { + t := s.T() + + metadata1 := modelMetadata.Metadata{ + Name: "job1", + ImageName: "job1-image-name", + Description: "desc1", + Author: "Test User