package main import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // TestUpdateUserMaxDevices tests the admin endpoint for updating user device cap func TestUpdateUserMaxDevices(t *testing.T) { ts, db, _, _ := setupTestServer(t) defer ts.Close() // Create test user with admin role adminToken := loginTestUser(t, ts, db) createAdminUser(t, ts, adminToken) // Login as admin to get admin token adminUserID := getTestUserID(t, db) adminToken = getAdminToken(t, ts, adminUserID) // Create a test user userID := createTestUserForMaxDevices(t, ts, adminToken) tests := []struct { name string maxDevices int32 expectedStatus int expectedBody string }{ { name: "Update to 5 devices", maxDevices: 5, expectedStatus: http.StatusOK, expectedBody: `{"message":"max devices updated"}`, }, { name: "Update to 10 devices (default)", maxDevices: 10, expectedStatus: http.StatusOK, expectedBody: `{"message":"max devices updated"}`, }, { name: "Update to 50 devices", maxDevices: 50, expectedStatus: http.StatusOK, expectedBody: `{"message":"max devices updated"}`, }, { name: "Update to 100 devices (maximum)", maxDevices: 100, expectedStatus: http.StatusOK, expectedBody: `{"message":"max devices updated"}`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { payload := map[string]interface{}{ "max_devices": tt.maxDevices, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("PUT", ts.URL+"/api/auth/users/"+userID.String()+"/max-devices", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+adminToken) client := &http.Client{} resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, tt.expectedStatus, resp.StatusCode, "expected status code") body := new(bytes.Buffer) body.ReadFrom(resp.Body) assert.Equal(t, tt.expectedBody, body.String(), "expected response body") }) } } // TestUpdateUserMaxDevicesValidation tests validation of max_devices parameter func TestUpdateUserMaxDevicesValidation(t *testing.T) { ts, db, _, _ := setupTestServer(t) defer ts.Close() // Create admin user and get token adminToken := loginTestUser(t, ts, db) createAdminUser(t, ts, adminToken) adminUserID := getTestUserID(t, db) adminToken = getAdminToken(t, ts, adminUserID) // Create test user userID := createTestUserForMaxDevices(t, ts, adminToken) tests := []struct { name string maxDevices int32 expectedStatus int }{ { name: "Zero devices (below minimum)", maxDevices: 0, expectedStatus: http.StatusBadRequest, }, { name: "Negative devices", maxDevices: -1, expectedStatus: http.StatusBadRequest, }, { name: "101 devices (above maximum)", maxDevices: 101, expectedStatus: http.StatusBadRequest, }, { name: "1000 devices (far above maximum)", maxDevices: 1000, expectedStatus: http.StatusBadRequest, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { payload := map[string]interface{}{ "max_devices": tt.maxDevices, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("PUT", ts.URL+"/api/auth/users/"+userID.String()+"/max-devices", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+adminToken) client := &http.Client{} resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, tt.expectedStatus, resp.StatusCode, "expected validation error") }) } } // TestUpdateUserMaxDevicesAuth tests authentication requirements func TestUpdateUserMaxDevicesAuth(t *testing.T) { ts, db, _, _ := setupTestServer(t) defer ts.Close() // Create admin user adminToken := loginTestUser(t, ts, db) createAdminUser(t, ts, adminToken) adminUserID := getTestUserID(t, db) adminToken = getAdminToken(t, ts, adminUserID) // Create regular user userID := createTestUserForMaxDevices(t, ts, adminToken) t.Run("No authorization", func(t *testing.T) { payload := map[string]interface{}{ "max_devices": 10, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("PUT", ts.URL+"/api/auth/users/"+userID.String()+"/max-devices", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("Non-admin user", func(t *testing.T) { // Create another regular user and get their token _ = createTestUserForMaxDevices(t, ts, adminToken) regularToken := loginTestUserByCredentials(t, ts, "regularuser@example.com", "Test@Pass123!") payload := map[string]interface{}{ "max_devices": 10, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("PUT", ts.URL+"/api/auth/users/"+userID.String()+"/max-devices", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+regularToken) client := &http.Client{} resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusForbidden, resp.StatusCode) }) } // TestUpdateUserMaxDevicesNonExistentUser tests with non-existent user ID func TestUpdateUserMaxDevicesNonExistentUser(t *testing.T) { ts, db, _, _ := setupTestServer(t) defer ts.Close() // Create admin user adminToken := loginTestUser(t, ts, db) createAdminUser(t, ts, adminToken) adminUserID := getTestUserID(t, db) adminToken = getAdminToken(t, ts, adminUserID) // Use a non-existent user ID nonExistentUserID := uuid.New() payload := map[string]interface{}{ "max_devices": 10, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("PUT", ts.URL+"/api/auth/users/"+nonExistentUserID.String()+"/max-devices", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+adminToken) client := &http.Client{} resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() // Should return 500 or 404 depending on implementation assert.True(t, resp.StatusCode == http.StatusInternalServerError || resp.StatusCode == http.StatusNotFound) } // TestUpdateUserMaxDevicesMissingUserID tests with missing user ID in URL func TestUpdateUserMaxDevicesMissingUserID(t *testing.T) { ts, db, _, _ := setupTestServer(t) defer ts.Close() // Create admin user adminToken := loginTestUser(t, ts, db) createAdminUser(t, ts, adminToken) adminUserID := getTestUserID(t, db) adminToken = getAdminToken(t, ts, adminUserID) payload := map[string]interface{}{ "max_devices": 10, } jsonData, _ := json.Marshal(payload) // Missing user ID in URL req, _ := http.NewRequest("PUT", ts.URL+"/api/auth/users//max-devices", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+adminToken) client := &http.Client{} resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusBadRequest, resp.StatusCode) } // TestListUsersIncludesMaxDevices tests that List Users returns max_devices field func TestListUsersIncludesMaxDevices(t *testing.T) { ts, db, _, _ := setupTestServer(t) defer ts.Close() // Create admin user adminToken := loginTestUser(t, ts, db) createAdminUser(t, ts, adminToken) adminUserID := getTestUserID(t, db) adminToken = getAdminToken(t, ts, adminUserID) req, _ := http.NewRequest("GET", ts.URL+"/api/auth/users", nil) req.Header.Set("Authorization", "Bearer "+adminToken) client := &http.Client{} resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) var users []map[string]interface{} json.NewDecoder(resp.Body).Decode(&users) // Verify max_devices field is present in response if len(users) > 0 { _, hasMaxDevices := users[0]["max_devices"] assert.True(t, hasMaxDevices, "max_devices field should be present in user list") } } // Helper function to create admin user func createAdminUser(t *testing.T, ts *httptest.Server, token string) { createUserPayload := map[string]interface{}{ "email": "admin@example.com", "username": "adminuser", "password": "Admin@Pass123!", "first_name": "Admin", "last_name": "User", "role": "admin", } jsonData, _ := json.Marshal(createUserPayload) req, _ := http.NewRequest("POST", ts.URL+"/api/auth/register", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+token) client := &http.Client{} resp, _ := client.Do(req) resp.Body.Close() } // Helper function to create test user for max devices tests func createTestUserForMaxDevices(t *testing.T, ts *httptest.Server, adminToken string) uuid.UUID { createUserPayload := map[string]interface{}{ "email": "maxdevices@example.com", "username": "maxdevicesuser", "password": "Test@Pass123!", "first_name": "Test", "last_name": "User", } jsonData, _ := json.Marshal(createUserPayload) req, _ := http.NewRequest("POST", ts.URL+"/api/auth/register", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+adminToken) client := &http.Client{} resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) userIDStr := result["user"].(map[string]interface{})["id"].(string) userID, _ := uuid.Parse(userIDStr) return userID } // Helper function to get admin token func getAdminToken(t *testing.T, ts *httptest.Server, userID uuid.UUID) string { // Now login as admin loginPayload := map[string]interface{}{ "login": "admin@example.com", "password": "Admin@Pass123!", } jsonData, _ := json.Marshal(loginPayload) req, _ := http.NewRequest("POST", ts.URL+"/api/auth/login", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) token := result["access_token"].(string) return token } // Helper function to login user by credentials func loginTestUserByCredentials(t *testing.T, ts *httptest.Server, email, password string) string { loginPayload := map[string]interface{}{ "login": email, "password": password, } jsonData, _ := json.Marshal(loginPayload) req, _ := http.NewRequest("POST", ts.URL+"/api/auth/login", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) return result["access_token"].(string) }