package v1 import ( "encoding/base64" "fmt" "github.com/go-chi/chi/v5" "github.com/muety/wakapi/middlewares" "github.com/muety/wakapi/mocks" "github.com/muety/wakapi/models" "io/ioutil" "net/http" "net/http/httptest" "strings" "testing" "time" ) var ( adminUser = &models.User{ ID: "AdminUser", ApiKey: "admin-user-api-key", Email: "admin@user.com", IsAdmin: true, CreatedAt: models.CustomTime(time.Date(2022, 2, 2, 22, 22, 22, 1, time.UTC)), LastLoggedInAt: models.CustomTime(time.Date(2022, 2, 2, 22, 22, 22, 2, time.UTC)), } basicUser = &models.User{ ID: "BasicUser", ApiKey: "basic-user-api-key", Email: "basic@user.com", IsAdmin: false, CreatedAt: models.CustomTime(time.Date(2022, 2, 2, 22, 22, 22, 3, time.UTC)), LastLoggedInAt: models.CustomTime(time.Date(2022, 2, 2, 22, 22, 22, 4, time.UTC)), } ) func TestUsersHandler_Get(t *testing.T) { router := chi.NewRouter() apiRouter := chi.NewRouter() apiRouter.Use(middlewares.NewPrincipalMiddleware()) router.Mount("/api", apiRouter) userServiceMock := new(mocks.UserServiceMock) userServiceMock.On("GetUserById", "AdminUser").Return(adminUser, nil) userServiceMock.On("GetUserByKey", "admin-user-api-key").Return(adminUser, nil) userServiceMock.On("GetUserById", "BasicUser").Return(basicUser, nil) userServiceMock.On("GetUserByKey", "basic-user-api-key").Return(basicUser, nil) heartbeatServiceMock := new(mocks.HeartbeatServiceMock) heartbeatServiceMock.On("GetLatestByUser", adminUser).Return(&models.Heartbeat{ CreatedAt: models.CustomTime(time.Date(2022, 2, 2, 22, 22, 22, 5, time.UTC)), Time: models.CustomTime(time.Date(2022, 2, 2, 22, 22, 22, 6, time.UTC)), }, nil) heartbeatServiceMock.On("GetLatestByUser", basicUser).Return(&models.Heartbeat{ CreatedAt: models.CustomTime(time.Date(2022, 2, 2, 22, 22, 22, 5, time.UTC)), Time: models.CustomTime(time.Date(2022, 2, 2, 22, 22, 22, 6, time.UTC)), }, nil) usersHandler := NewUsersHandler(userServiceMock, heartbeatServiceMock) usersHandler.RegisterRoutes(apiRouter) t.Run("when requesting own user data", func(t *testing.T) { t.Run("should return own data", func(t *testing.T) { rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodGet, "/api/compat/wakatime/v1/users/{user}", nil) req = withUrlParam(req, "user", "AdminUser") req.Header.Add( "Authorization", fmt.Sprintf("Bearer %s", base64.StdEncoding.EncodeToString([]byte(adminUser.ApiKey))), ) router.ServeHTTP(rec, req) res := rec.Result() defer res.Body.Close() data, err := ioutil.ReadAll(res.Body) if err != nil { t.Errorf("unexpected error. Error: %s", err) } if !strings.Contains(string(data), "\"username\":\"AdminUser\"") { t.Errorf("invalid response received. Expected json Received: %s", string(data)) } }) }) t.Run("when requesting another users data", func(t *testing.T) { t.Run("should respond with '401 unauthorized' if not an admin user", func(t *testing.T) { rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodGet, "/api/compat/wakatime/v1/users/{user}", nil) req = withUrlParam(req, "user", "AdminUser") req.Header.Add( "Authorization", fmt.Sprintf("Bearer %s", base64.StdEncoding.EncodeToString([]byte(basicUser.ApiKey))), ) router.ServeHTTP(rec, req) res := rec.Result() defer res.Body.Close() data, err := ioutil.ReadAll(res.Body) if err != nil { t.Errorf("unextected error. Error: %s", err) } if string(data) != "401 unauthorized" { t.Errorf("invalid response received. Expected: '401 unauthorized' Received: %s", string(data)) } }) t.Run("should receive user data if requesting user is an admin", func(t *testing.T) { rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodGet, "/api/compat/wakatime/v1/users/{user}", nil) req = withUrlParam(req, "user", "BasicUser") req.Header.Add( "Authorization", fmt.Sprintf("Bearer %s", base64.StdEncoding.EncodeToString([]byte(adminUser.ApiKey))), ) router.ServeHTTP(rec, req) res := rec.Result() defer res.Body.Close() data, err := ioutil.ReadAll(res.Body) if err != nil { t.Errorf("unextected error. Error: %s", err) } if !strings.Contains(string(data), "\"username\":\"BasicUser\"") { t.Errorf("invalid response received. Expected 'BasicUser' info Received: %s", string(data)) } }) }) }