package apis import ( "bytes" "clortho/lib/db" "clortho/lib/users" "encoding/json" "fmt" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "net/http" "net/http/httptest" "testing" ) func setupUsersRouter() *gin.Engine { r := gin.Default() private := r.Group("/gui") InitUsersEndpoints(private) return r } func createTestUserForEndpoint(admin bool) *db.User { username := fmt.Sprintf("testuser_%d", db.Connection.RowsAffected) if admin { username = fmt.Sprintf("admin_%d", db.Connection.RowsAffected) } displayName := username user := db.User{ Username: username, DisplayName: &displayName, Admin: admin, } db.Connection.Create(&user) return &user } func TestGetUsers(t *testing.T) { // Setup router := setupUsersRouter() // Create admin user and session adminUser := createTestUserForEndpoint(true) adminSession := users.NewSession(*adminUser) // Set admin session in context router.Use(func(c *gin.Context) { c.Set("session", adminSession) c.Next() }) // Test getting all users w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/gui/users/", nil) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var userList []db.User err := json.Unmarshal(w.Body.Bytes(), &userList) assert.NoError(t, err) assert.NotEmpty(t, userList) } func TestGetUser(t *testing.T) { // Setup router := setupUsersRouter() // Create admin user and session adminUser := createTestUserForEndpoint(true) adminSession := users.NewSession(*adminUser) // Set admin session in context router.Use(func(c *gin.Context) { c.Set("session", adminSession) c.Next() }) // Test getting a specific user w := httptest.NewRecorder() req, _ := http.NewRequest("GET", fmt.Sprintf("/gui/users/%d", adminUser.ID), nil) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var user db.User err := json.Unmarshal(w.Body.Bytes(), &user) assert.NoError(t, err) assert.Equal(t, adminUser.ID, user.ID) assert.Equal(t, adminUser.Username, user.Username) } func TestCreateUser(t *testing.T) { // Setup router := setupUsersRouter() // Create admin user and session adminUser := createTestUserForEndpoint(true) adminSession := users.NewSession(*adminUser) // Set admin session in context router.Use(func(c *gin.Context) { c.Set("session", adminSession) c.Next() }) // Test creating a new user userReq := userRequest{ Username: "newuser", DisplayName: "New User", Admin: false, } reqBody, _ := json.Marshal(userReq) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/gui/users/", bytes.NewBuffer(reqBody)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusCreated, w.Code) var user db.User err := json.Unmarshal(w.Body.Bytes(), &user) assert.NoError(t, err) assert.Equal(t, userReq.Username, user.Username) assert.Equal(t, userReq.DisplayName, *user.DisplayName) assert.Equal(t, userReq.Admin, user.Admin) } func TestUpdateUser(t *testing.T) { // Setup router := setupUsersRouter() // Create admin user and session adminUser := createTestUserForEndpoint(true) adminSession := users.NewSession(*adminUser) // Create a regular user to update regularUser := createTestUserForEndpoint(false) // Set admin session in context router.Use(func(c *gin.Context) { c.Set("session", adminSession) c.Next() }) // Test updating a user updateReq := userUpdateRequest{ DisplayName: "Updated User", Admin: true, } reqBody, _ := json.Marshal(updateReq) w := httptest.NewRecorder() req, _ := http.NewRequest("PUT", fmt.Sprintf("/gui/users/%d", regularUser.ID), bytes.NewBuffer(reqBody)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var user db.User err := json.Unmarshal(w.Body.Bytes(), &user) assert.NoError(t, err) assert.Equal(t, regularUser.ID, user.ID) assert.Equal(t, regularUser.Username, user.Username) assert.Equal(t, updateReq.DisplayName, *user.DisplayName) assert.Equal(t, updateReq.Admin, user.Admin) } func TestDeleteUser(t *testing.T) { // Setup router := setupUsersRouter() // Create admin user and session adminUser := createTestUserForEndpoint(true) adminSession := users.NewSession(*adminUser) // Create a regular user to delete regularUser := createTestUserForEndpoint(false) // Set admin session in context router.Use(func(c *gin.Context) { c.Set("session", adminSession) c.Next() }) // Test deleting a user w := httptest.NewRecorder() req, _ := http.NewRequest("DELETE", fmt.Sprintf("/gui/users/%d", regularUser.ID), nil) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) // Verify the user was deleted var response map[string]string err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.Equal(t, "User deleted successfully", response["message"]) // Try to get the deleted user w = httptest.NewRecorder() req, _ = http.NewRequest("GET", fmt.Sprintf("/gui/users/%d", regularUser.ID), nil) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusNotFound, w.Code) } func TestDeleteSelf(t *testing.T) { // Setup router := setupUsersRouter() // Create admin user and session adminUser := createTestUserForEndpoint(true) adminSession := users.NewSession(*adminUser) // Set admin session in context router.Use(func(c *gin.Context) { c.Set("session", adminSession) c.Next() }) // Test deleting self w := httptest.NewRecorder() req, _ := http.NewRequest("DELETE", fmt.Sprintf("/gui/users/%d", adminUser.ID), nil) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) // Verify the error message var response map[string]string err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.Equal(t, "Cannot delete your own account", response["error"]) }