mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-06 07:54:22 +00:00
Update handler integration tests
This commit is contained in:
@@ -34,8 +34,8 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("user management", func(t *testing.T) {
|
t.Run("user management", func(t *testing.T) {
|
||||||
t.Run("list users", func(t *testing.T) {
|
t.Run("list users", func(t *testing.T) {
|
||||||
// Test with admin token
|
// Test with admin session
|
||||||
rr := h.makeRequest(t, http.MethodGet, "/api/v1/admin/users", nil, h.AdminToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, "/api/v1/admin/users", nil, h.AdminSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var users []*models.User
|
var users []*models.User
|
||||||
@@ -47,12 +47,12 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
assert.True(t, containsUser(users, h.AdminUser), "Admin user not found in users list")
|
assert.True(t, containsUser(users, h.AdminUser), "Admin user not found in users list")
|
||||||
assert.True(t, containsUser(users, h.RegularUser), "Regular user not found in users list")
|
assert.True(t, containsUser(users, h.RegularUser), "Regular user not found in users list")
|
||||||
|
|
||||||
// Test with non-admin token
|
// Test with non-admin session
|
||||||
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/users", nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/users", nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusForbidden, rr.Code)
|
assert.Equal(t, http.StatusForbidden, rr.Code)
|
||||||
|
|
||||||
// Test without token
|
// Test without session
|
||||||
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/users", nil, "", nil)
|
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/users", nil, nil, nil)
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -64,8 +64,8 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
Role: models.RoleEditor,
|
Role: models.RoleEditor,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test with admin token
|
// Test with admin session
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", createReq, h.AdminToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", createReq, h.AdminSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var createdUser models.User
|
var createdUser models.User
|
||||||
@@ -77,7 +77,7 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
assert.NotZero(t, createdUser.LastWorkspaceID)
|
assert.NotZero(t, createdUser.LastWorkspaceID)
|
||||||
|
|
||||||
// Test duplicate email
|
// Test duplicate email
|
||||||
rr = h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", createReq, h.AdminToken, nil)
|
rr = h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", createReq, h.AdminSession, nil)
|
||||||
assert.Equal(t, http.StatusConflict, rr.Code)
|
assert.Equal(t, http.StatusConflict, rr.Code)
|
||||||
|
|
||||||
// Test invalid request (missing required fields)
|
// Test invalid request (missing required fields)
|
||||||
@@ -85,19 +85,19 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
Email: "invalid@test.com",
|
Email: "invalid@test.com",
|
||||||
// Missing password and role
|
// Missing password and role
|
||||||
}
|
}
|
||||||
rr = h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", invalidReq, h.AdminToken, nil)
|
rr = h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", invalidReq, h.AdminSession, nil)
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
||||||
|
|
||||||
// Test with non-admin token
|
// Test with non-admin session
|
||||||
rr = h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", createReq, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", createReq, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusForbidden, rr.Code)
|
assert.Equal(t, http.StatusForbidden, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get user", func(t *testing.T) {
|
t.Run("get user", func(t *testing.T) {
|
||||||
path := fmt.Sprintf("/api/v1/admin/users/%d", h.RegularUser.ID)
|
path := fmt.Sprintf("/api/v1/admin/users/%d", h.RegularUser.ID)
|
||||||
|
|
||||||
// Test with admin token
|
// Test with admin session
|
||||||
rr := h.makeRequest(t, http.MethodGet, path, nil, h.AdminToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, path, nil, h.AdminSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var user models.User
|
var user models.User
|
||||||
@@ -106,11 +106,11 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
assert.Equal(t, h.RegularUser.ID, user.ID)
|
assert.Equal(t, h.RegularUser.ID, user.ID)
|
||||||
|
|
||||||
// Test non-existent user
|
// Test non-existent user
|
||||||
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/users/999999", nil, h.AdminToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/users/999999", nil, h.AdminSession, nil)
|
||||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||||
|
|
||||||
// Test with non-admin token
|
// Test with non-admin session
|
||||||
rr = h.makeRequest(t, http.MethodGet, path, nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, path, nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusForbidden, rr.Code)
|
assert.Equal(t, http.StatusForbidden, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -121,8 +121,8 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
Role: models.RoleViewer,
|
Role: models.RoleViewer,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test with admin token
|
// Test with admin session
|
||||||
rr := h.makeRequest(t, http.MethodPut, path, updateReq, h.AdminToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, path, updateReq, h.AdminSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var updatedUser models.User
|
var updatedUser models.User
|
||||||
@@ -131,8 +131,8 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
assert.Equal(t, updateReq.DisplayName, updatedUser.DisplayName)
|
assert.Equal(t, updateReq.DisplayName, updatedUser.DisplayName)
|
||||||
assert.Equal(t, updateReq.Role, updatedUser.Role)
|
assert.Equal(t, updateReq.Role, updatedUser.Role)
|
||||||
|
|
||||||
// Test with non-admin token
|
// Test with non-admin session
|
||||||
rr = h.makeRequest(t, http.MethodPut, path, updateReq, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodPut, path, updateReq, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusForbidden, rr.Code)
|
assert.Equal(t, http.StatusForbidden, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
Role: models.RoleEditor,
|
Role: models.RoleEditor,
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", createReq, h.AdminToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", createReq, h.AdminSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var createdUser models.User
|
var createdUser models.User
|
||||||
@@ -156,19 +156,19 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
// Test deleting own account (should fail)
|
// Test deleting own account (should fail)
|
||||||
adminPath := fmt.Sprintf("/api/v1/admin/users/%d", h.AdminUser.ID)
|
adminPath := fmt.Sprintf("/api/v1/admin/users/%d", h.AdminUser.ID)
|
||||||
rr = h.makeRequest(t, http.MethodDelete, adminPath, nil, h.AdminToken, nil)
|
rr = h.makeRequest(t, http.MethodDelete, adminPath, nil, h.AdminSession, nil)
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
||||||
|
|
||||||
// Test with admin token
|
// Test with admin session
|
||||||
rr = h.makeRequest(t, http.MethodDelete, path, nil, h.AdminToken, nil)
|
rr = h.makeRequest(t, http.MethodDelete, path, nil, h.AdminSession, nil)
|
||||||
assert.Equal(t, http.StatusNoContent, rr.Code)
|
assert.Equal(t, http.StatusNoContent, rr.Code)
|
||||||
|
|
||||||
// Verify user is deleted
|
// Verify user is deleted
|
||||||
rr = h.makeRequest(t, http.MethodGet, path, nil, h.AdminToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, path, nil, h.AdminSession, nil)
|
||||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||||
|
|
||||||
// Test with non-admin token
|
// Test with non-admin session
|
||||||
rr = h.makeRequest(t, http.MethodDelete, path, nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodDelete, path, nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusForbidden, rr.Code)
|
assert.Equal(t, http.StatusForbidden, rr.Code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -181,11 +181,11 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
Name: "Test Workspace",
|
Name: "Test Workspace",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
// Test with admin token
|
// Test with admin session
|
||||||
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/workspaces", nil, h.AdminToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/workspaces", nil, h.AdminSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var workspaces []*handlers.WorkspaceStats
|
var workspaces []*handlers.WorkspaceStats
|
||||||
@@ -206,8 +206,8 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
assert.GreaterOrEqual(t, ws.TotalSize, int64(0))
|
assert.GreaterOrEqual(t, ws.TotalSize, int64(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test with non-admin token
|
// Test with non-admin session
|
||||||
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/workspaces", nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/workspaces", nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusForbidden, rr.Code)
|
assert.Equal(t, http.StatusForbidden, rr.Code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -218,11 +218,11 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
UserID: h.RegularUser.ID,
|
UserID: h.RegularUser.ID,
|
||||||
Name: "Stats Test Workspace",
|
Name: "Stats Test Workspace",
|
||||||
}
|
}
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
// Test with admin token
|
// Test with admin session
|
||||||
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/stats", nil, h.AdminToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/stats", nil, h.AdminSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var stats handlers.SystemStats
|
var stats handlers.SystemStats
|
||||||
@@ -236,8 +236,8 @@ func TestAdminHandlers_Integration(t *testing.T) {
|
|||||||
assert.GreaterOrEqual(t, stats.TotalFiles, 0)
|
assert.GreaterOrEqual(t, stats.TotalFiles, 0)
|
||||||
assert.GreaterOrEqual(t, stats.TotalSize, int64(0))
|
assert.GreaterOrEqual(t, stats.TotalSize, int64(0))
|
||||||
|
|
||||||
// Test with non-admin token
|
// Test with non-admin session
|
||||||
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/stats", nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, "/api/v1/admin/stats", nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusForbidden, rr.Code)
|
assert.Equal(t, http.StatusForbidden, rr.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ package handlers_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"novamd/internal/handlers"
|
"novamd/internal/handlers"
|
||||||
"novamd/internal/models"
|
"novamd/internal/models"
|
||||||
@@ -25,40 +29,58 @@ func TestAuthHandlers_Integration(t *testing.T) {
|
|||||||
Password: "admin123",
|
Password: "admin123",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", loginReq, "", nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", loginReq, nil, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
|
// Verify all required cookies are present with correct attributes
|
||||||
|
cookies := rr.Result().Cookies()
|
||||||
|
var foundAccessToken, foundRefreshToken, foundCSRF bool
|
||||||
|
for _, cookie := range cookies {
|
||||||
|
switch cookie.Name {
|
||||||
|
case "access_token":
|
||||||
|
foundAccessToken = true
|
||||||
|
assert.True(t, cookie.HttpOnly, "access_token cookie must be HttpOnly")
|
||||||
|
assert.Equal(t, http.SameSiteStrictMode, cookie.SameSite)
|
||||||
|
assert.Equal(t, 900, cookie.MaxAge) // 15 minutes
|
||||||
|
case "refresh_token":
|
||||||
|
foundRefreshToken = true
|
||||||
|
assert.True(t, cookie.HttpOnly, "refresh_token cookie must be HttpOnly")
|
||||||
|
assert.Equal(t, http.SameSiteStrictMode, cookie.SameSite)
|
||||||
|
assert.Equal(t, 604800, cookie.MaxAge) // 7 days
|
||||||
|
case "csrf_token":
|
||||||
|
foundCSRF = true
|
||||||
|
assert.False(t, cookie.HttpOnly, "csrf_token cookie must not be HttpOnly")
|
||||||
|
assert.Equal(t, http.SameSiteStrictMode, cookie.SameSite)
|
||||||
|
assert.Equal(t, 900, cookie.MaxAge) // 15 minutes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.True(t, foundAccessToken, "access_token cookie not found")
|
||||||
|
assert.True(t, foundRefreshToken, "refresh_token cookie not found")
|
||||||
|
assert.True(t, foundCSRF, "csrf_token cookie not found")
|
||||||
|
|
||||||
|
// Verify CSRF token is in both cookie and header, and they match
|
||||||
|
var csrfCookie *http.Cookie
|
||||||
|
for _, cookie := range rr.Result().Cookies() {
|
||||||
|
if cookie.Name == "csrf_token" {
|
||||||
|
csrfCookie = cookie
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotNil(t, csrfCookie, "csrf_token cookie not found")
|
||||||
|
csrfHeader := rr.Header().Get("X-CSRF-Token")
|
||||||
|
assert.Equal(t, csrfCookie.Value, csrfHeader)
|
||||||
|
|
||||||
|
// Verify response body
|
||||||
var resp handlers.LoginResponse
|
var resp handlers.LoginResponse
|
||||||
err := json.NewDecoder(rr.Body).Decode(&resp)
|
err := json.NewDecoder(rr.Body).Decode(&resp)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, resp.SessionID)
|
||||||
assert.NotEmpty(t, resp.AccessToken)
|
assert.False(t, resp.ExpiresAt.IsZero())
|
||||||
assert.NotEmpty(t, resp.RefreshToken)
|
|
||||||
assert.NotNil(t, resp.User)
|
assert.NotNil(t, resp.User)
|
||||||
assert.Equal(t, loginReq.Email, resp.User.Email)
|
assert.Equal(t, loginReq.Email, resp.User.Email)
|
||||||
assert.Equal(t, models.RoleAdmin, resp.User.Role)
|
assert.Equal(t, models.RoleAdmin, resp.User.Role)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("successful login - regular user", func(t *testing.T) {
|
|
||||||
loginReq := handlers.LoginRequest{
|
|
||||||
Email: "user@test.com",
|
|
||||||
Password: "user123",
|
|
||||||
}
|
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", loginReq, "", nil)
|
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
|
||||||
|
|
||||||
var resp handlers.LoginResponse
|
|
||||||
err := json.NewDecoder(rr.Body).Decode(&resp)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
assert.NotEmpty(t, resp.AccessToken)
|
|
||||||
assert.NotEmpty(t, resp.RefreshToken)
|
|
||||||
assert.NotNil(t, resp.User)
|
|
||||||
assert.Equal(t, loginReq.Email, resp.User.Email)
|
|
||||||
assert.Equal(t, models.RoleEditor, resp.User.Role)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("login failures", func(t *testing.T) {
|
t.Run("login failures", func(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -97,12 +119,26 @@ func TestAuthHandlers_Integration(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantCode: http.StatusBadRequest,
|
wantCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "malformed JSON",
|
||||||
|
request: handlers.LoginRequest{}, // Will be overridden with bad JSON
|
||||||
|
wantCode: http.StatusBadRequest,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", tt.request, "", nil)
|
var rr *httptest.ResponseRecorder
|
||||||
|
if tt.name == "malformed JSON" {
|
||||||
|
// Need lower level helper to send malformed JSON
|
||||||
|
req := h.newRequest(t, http.MethodPost, "/api/v1/auth/login", nil)
|
||||||
|
req.Body = io.NopCloser(strings.NewReader("{bad json"))
|
||||||
|
rr = h.executeRequest(req)
|
||||||
|
} else {
|
||||||
|
rr = h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", tt.request, nil, nil)
|
||||||
|
}
|
||||||
assert.Equal(t, tt.wantCode, rr.Code)
|
assert.Equal(t, tt.wantCode, rr.Code)
|
||||||
|
assert.Empty(t, rr.Result().Cookies(), "failed login should not set cookies")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -110,58 +146,76 @@ func TestAuthHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("refresh token", func(t *testing.T) {
|
t.Run("refresh token", func(t *testing.T) {
|
||||||
t.Run("successful token refresh", func(t *testing.T) {
|
t.Run("successful token refresh", func(t *testing.T) {
|
||||||
// First login to get refresh token
|
// Need lower level helpers for precise cookie control
|
||||||
loginReq := handlers.LoginRequest{
|
req := h.newRequest(t, http.MethodPost, "/api/v1/auth/refresh", nil)
|
||||||
Email: "user@test.com",
|
h.addAuthCookies(t, req, h.RegularSession, true) // Adds both tokens
|
||||||
Password: "user123",
|
rr := h.executeRequest(req)
|
||||||
}
|
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", loginReq, "", nil)
|
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var loginResp handlers.LoginResponse
|
// Verify new cookies
|
||||||
err := json.NewDecoder(rr.Body).Decode(&loginResp)
|
cookies := rr.Result().Cookies()
|
||||||
require.NoError(t, err)
|
var foundAccessToken, foundCSRF bool
|
||||||
|
for _, cookie := range cookies {
|
||||||
// Now try to refresh the token
|
switch cookie.Name {
|
||||||
refreshReq := handlers.RefreshRequest{
|
case "access_token":
|
||||||
RefreshToken: loginResp.RefreshToken,
|
foundAccessToken = true
|
||||||
|
assert.Equal(t, 900, cookie.MaxAge)
|
||||||
|
case "csrf_token":
|
||||||
|
foundCSRF = true
|
||||||
|
assert.Equal(t, 900, cookie.MaxAge)
|
||||||
|
case "refresh_token":
|
||||||
|
t.Error("refresh token should not be renewed")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
rr = h.makeRequest(t, http.MethodPost, "/api/v1/auth/refresh", refreshReq, "", nil)
|
assert.True(t, foundAccessToken, "new access_token cookie not found")
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
assert.True(t, foundCSRF, "new csrf_token cookie not found")
|
||||||
|
|
||||||
var refreshResp handlers.RefreshResponse
|
|
||||||
err = json.NewDecoder(rr.Body).Decode(&refreshResp)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.NotEmpty(t, refreshResp.AccessToken)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("refresh failures", func(t *testing.T) {
|
t.Run("refresh token edge cases", func(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
request handlers.RefreshRequest
|
setup func(*http.Request)
|
||||||
wantCode int
|
wantCode int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "invalid refresh token",
|
name: "missing refresh token cookie",
|
||||||
request: handlers.RefreshRequest{
|
setup: func(req *http.Request) {
|
||||||
RefreshToken: "invalid-token",
|
// Only add access token
|
||||||
|
token, _ := h.JWTManager.GenerateAccessToken(h.RegularSession.UserID, "admin")
|
||||||
|
req.AddCookie(h.CookieManager.GenerateAccessTokenCookie(token))
|
||||||
|
},
|
||||||
|
wantCode: http.StatusBadRequest,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "expired refresh token",
|
||||||
|
setup: func(req *http.Request) {
|
||||||
|
expiredSession := &models.Session{
|
||||||
|
ID: "expired",
|
||||||
|
UserID: h.RegularUser.ID,
|
||||||
|
RefreshToken: "expired-token",
|
||||||
|
ExpiresAt: time.Now().Add(-1 * time.Hour),
|
||||||
|
}
|
||||||
|
h.addAuthCookies(t, req, expiredSession, true)
|
||||||
},
|
},
|
||||||
wantCode: http.StatusUnauthorized,
|
wantCode: http.StatusUnauthorized,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty refresh token",
|
name: "invalid refresh token format",
|
||||||
request: handlers.RefreshRequest{
|
setup: func(req *http.Request) {
|
||||||
RefreshToken: "",
|
req.AddCookie(&http.Cookie{
|
||||||
|
Name: "refresh_token",
|
||||||
|
Value: "invalid-format",
|
||||||
|
})
|
||||||
},
|
},
|
||||||
wantCode: http.StatusBadRequest,
|
wantCode: http.StatusUnauthorized,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/auth/refresh", tt.request, "", nil)
|
req := h.newRequest(t, http.MethodPost, "/api/v1/auth/refresh", nil)
|
||||||
|
tt.setup(req)
|
||||||
|
rr := h.executeRequest(req)
|
||||||
assert.Equal(t, tt.wantCode, rr.Code)
|
assert.Equal(t, tt.wantCode, rr.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -170,63 +224,136 @@ func TestAuthHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("logout", func(t *testing.T) {
|
t.Run("logout", func(t *testing.T) {
|
||||||
t.Run("successful logout", func(t *testing.T) {
|
t.Run("successful logout", func(t *testing.T) {
|
||||||
// First login to get session
|
// Need CSRF token for POST request
|
||||||
loginReq := handlers.LoginRequest{
|
req := h.newRequest(t, http.MethodPost, "/api/v1/auth/logout", nil)
|
||||||
Email: "user@test.com",
|
csrfToken := h.addAuthCookies(t, req, h.RegularSession, true)
|
||||||
Password: "user123",
|
req.Header.Set("X-CSRF-Token", csrfToken)
|
||||||
}
|
rr := h.executeRequest(req)
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", loginReq, "", nil)
|
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
|
||||||
|
|
||||||
var loginResp handlers.LoginResponse
|
|
||||||
err := json.NewDecoder(rr.Body).Decode(&loginResp)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Now logout using session ID from login response
|
|
||||||
headers := map[string]string{
|
|
||||||
"X-Session-ID": loginResp.Session.ID,
|
|
||||||
}
|
|
||||||
rr = h.makeRequest(t, http.MethodPost, "/api/v1/auth/logout", nil, loginResp.AccessToken, headers)
|
|
||||||
require.Equal(t, http.StatusNoContent, rr.Code)
|
require.Equal(t, http.StatusNoContent, rr.Code)
|
||||||
|
|
||||||
// Try to use the refresh token - should fail
|
// Verify cookies are properly invalidated
|
||||||
refreshReq := handlers.RefreshRequest{
|
for _, cookie := range rr.Result().Cookies() {
|
||||||
RefreshToken: loginResp.RefreshToken,
|
assert.True(t, cookie.MaxAge < 0, "cookie should be invalidated")
|
||||||
|
assert.True(t, cookie.Expires.Before(time.Now()), "cookie should be expired")
|
||||||
}
|
}
|
||||||
|
|
||||||
rr = h.makeRequest(t, http.MethodPost, "/api/v1/auth/refresh", refreshReq, "", nil)
|
// Verify session is actually invalidated
|
||||||
|
rr = h.makeRequest(t, http.MethodGet, "/api/v1/auth/me", nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("logout without session ID", func(t *testing.T) {
|
t.Run("logout edge cases", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/auth/logout", nil, h.RegularToken, nil)
|
tests := []struct {
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
name string
|
||||||
|
setup func(*http.Request)
|
||||||
|
wantCode int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "missing CSRF token",
|
||||||
|
setup: func(req *http.Request) {
|
||||||
|
h.addAuthCookies(t, req, h.RegularSession, true)
|
||||||
|
// Deliberately not setting X-CSRF-Token header
|
||||||
|
},
|
||||||
|
wantCode: http.StatusForbidden,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mismatched CSRF token",
|
||||||
|
setup: func(req *http.Request) {
|
||||||
|
h.addAuthCookies(t, req, h.RegularSession, true)
|
||||||
|
req.Header.Set("X-CSRF-Token", "wrong-token")
|
||||||
|
},
|
||||||
|
wantCode: http.StatusForbidden,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "missing auth cookies",
|
||||||
|
setup: func(req *http.Request) {
|
||||||
|
// No setup - testing completely unauthenticated request
|
||||||
|
},
|
||||||
|
wantCode: http.StatusUnauthorized,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
req := h.newRequest(t, http.MethodPost, "/api/v1/auth/logout", nil)
|
||||||
|
tt.setup(req)
|
||||||
|
rr := h.executeRequest(req)
|
||||||
|
assert.Equal(t, tt.wantCode, rr.Code)
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get current user", func(t *testing.T) {
|
t.Run("get current user", func(t *testing.T) {
|
||||||
t.Run("successful get current user", func(t *testing.T) {
|
t.Run("successful get current user", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodGet, "/api/v1/auth/me", nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, "/api/v1/auth/me", nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var user models.User
|
var user models.User
|
||||||
err := json.NewDecoder(rr.Body).Decode(&user)
|
err := json.NewDecoder(rr.Body).Decode(&user)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, h.RegularUser.ID, user.ID)
|
|
||||||
assert.Equal(t, h.RegularUser.Email, user.Email)
|
assert.Equal(t, h.RegularUser.Email, user.Email)
|
||||||
assert.Equal(t, h.RegularUser.Role, user.Role)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get current user without token", func(t *testing.T) {
|
t.Run("auth edge cases", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodGet, "/api/v1/auth/me", nil, "", nil)
|
tests := []struct {
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
name string
|
||||||
|
setup func(*http.Request)
|
||||||
|
wantCode int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "missing auth cookie",
|
||||||
|
setup: func(req *http.Request) {
|
||||||
|
// No setup - testing unauthenticated request
|
||||||
|
},
|
||||||
|
wantCode: http.StatusUnauthorized,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid session ID",
|
||||||
|
setup: func(req *http.Request) {
|
||||||
|
invalidSession := &models.Session{
|
||||||
|
ID: "invalid",
|
||||||
|
UserID: 999,
|
||||||
|
RefreshToken: "invalid",
|
||||||
|
ExpiresAt: time.Now().Add(time.Hour),
|
||||||
|
}
|
||||||
|
h.addAuthCookies(t, req, invalidSession, false)
|
||||||
|
},
|
||||||
|
wantCode: http.StatusUnauthorized,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "expired session",
|
||||||
|
setup: func(req *http.Request) {
|
||||||
|
expiredSession := &models.Session{
|
||||||
|
ID: "expired",
|
||||||
|
UserID: h.RegularUser.ID,
|
||||||
|
RefreshToken: "expired-token",
|
||||||
|
ExpiresAt: time.Now().Add(-1 * time.Hour),
|
||||||
|
}
|
||||||
|
h.addAuthCookies(t, req, expiredSession, false)
|
||||||
|
},
|
||||||
|
wantCode: http.StatusUnauthorized,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "malformed access token",
|
||||||
|
setup: func(req *http.Request) {
|
||||||
|
req.AddCookie(&http.Cookie{
|
||||||
|
Name: "access_token",
|
||||||
|
Value: "malformed-token",
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
wantCode: http.StatusUnauthorized,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
t.Run("get current user with invalid token", func(t *testing.T) {
|
for _, tt := range tests {
|
||||||
rr := h.makeRequest(t, http.MethodGet, "/api/v1/auth/me", nil, "invalid-token", nil)
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
req := h.newRequest(t, http.MethodGet, "/api/v1/auth/me", nil)
|
||||||
|
tt.setup(req)
|
||||||
|
rr := h.executeRequest(req)
|
||||||
|
assert.Equal(t, tt.wantCode, rr.Code)
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func TestFileHandlers_Integration(t *testing.T) {
|
|||||||
UserID: h.RegularUser.ID,
|
UserID: h.RegularUser.ID,
|
||||||
Name: "File Test Workspace",
|
Name: "File Test Workspace",
|
||||||
}
|
}
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
err := json.NewDecoder(rr.Body).Decode(workspace)
|
err := json.NewDecoder(rr.Body).Decode(workspace)
|
||||||
@@ -37,7 +37,7 @@ func TestFileHandlers_Integration(t *testing.T) {
|
|||||||
baseURL := fmt.Sprintf("/api/v1/workspaces/%s/files", url.PathEscape(workspace.Name))
|
baseURL := fmt.Sprintf("/api/v1/workspaces/%s/files", url.PathEscape(workspace.Name))
|
||||||
|
|
||||||
t.Run("list empty directory", func(t *testing.T) {
|
t.Run("list empty directory", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodGet, baseURL, nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, baseURL, nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var files []storage.FileNode
|
var files []storage.FileNode
|
||||||
@@ -51,16 +51,16 @@ func TestFileHandlers_Integration(t *testing.T) {
|
|||||||
filePath := "test.md"
|
filePath := "test.md"
|
||||||
|
|
||||||
// Save file
|
// Save file
|
||||||
rr := h.makeRequestRaw(t, http.MethodPost, baseURL+"/"+filePath, strings.NewReader(content), h.RegularToken, nil)
|
rr := h.makeRequestRaw(t, http.MethodPost, baseURL+"/"+filePath, strings.NewReader(content), h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
// Get file content
|
// Get file content
|
||||||
rr = h.makeRequest(t, http.MethodGet, baseURL+"/"+filePath, nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, baseURL+"/"+filePath, nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
assert.Equal(t, content, rr.Body.String())
|
assert.Equal(t, content, rr.Body.String())
|
||||||
|
|
||||||
// List directory should now show the file
|
// List directory should now show the file
|
||||||
rr = h.makeRequest(t, http.MethodGet, baseURL, nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, baseURL, nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var files []storage.FileNode
|
var files []storage.FileNode
|
||||||
@@ -80,12 +80,12 @@ func TestFileHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
// Create all files
|
// Create all files
|
||||||
for path, content := range files {
|
for path, content := range files {
|
||||||
rr := h.makeRequest(t, http.MethodPost, baseURL+"/"+path, content, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, baseURL+"/"+path, content, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List all files
|
// List all files
|
||||||
rr := h.makeRequest(t, http.MethodGet, baseURL, nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, baseURL, nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var fileNodes []storage.FileNode
|
var fileNodes []storage.FileNode
|
||||||
@@ -116,11 +116,11 @@ func TestFileHandlers_Integration(t *testing.T) {
|
|||||||
// Look up a file that exists in multiple locations
|
// Look up a file that exists in multiple locations
|
||||||
filename := "readme.md"
|
filename := "readme.md"
|
||||||
dupContent := "Another readme"
|
dupContent := "Another readme"
|
||||||
rr := h.makeRequest(t, http.MethodPost, baseURL+"/projects/"+filename, dupContent, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, baseURL+"/projects/"+filename, dupContent, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
// Search for the file
|
// Search for the file
|
||||||
rr = h.makeRequest(t, http.MethodGet, baseURL+"/lookup?filename="+filename, nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, baseURL+"/lookup?filename="+filename, nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var response struct {
|
var response struct {
|
||||||
@@ -131,7 +131,7 @@ func TestFileHandlers_Integration(t *testing.T) {
|
|||||||
assert.Len(t, response.Paths, 2)
|
assert.Len(t, response.Paths, 2)
|
||||||
|
|
||||||
// Search for non-existent file
|
// Search for non-existent file
|
||||||
rr = h.makeRequest(t, http.MethodGet, baseURL+"/lookup?filename=nonexistent.md", nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, baseURL+"/lookup?filename=nonexistent.md", nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -140,21 +140,21 @@ func TestFileHandlers_Integration(t *testing.T) {
|
|||||||
content := "This file will be deleted"
|
content := "This file will be deleted"
|
||||||
|
|
||||||
// Create file
|
// Create file
|
||||||
rr := h.makeRequest(t, http.MethodPost, baseURL+"/"+filePath, content, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, baseURL+"/"+filePath, content, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
// Delete file
|
// Delete file
|
||||||
rr = h.makeRequest(t, http.MethodDelete, baseURL+"/"+filePath, nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodDelete, baseURL+"/"+filePath, nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusNoContent, rr.Code)
|
require.Equal(t, http.StatusNoContent, rr.Code)
|
||||||
|
|
||||||
// Verify file is gone
|
// Verify file is gone
|
||||||
rr = h.makeRequest(t, http.MethodGet, baseURL+"/"+filePath, nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, baseURL+"/"+filePath, nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("last opened file", func(t *testing.T) {
|
t.Run("last opened file", func(t *testing.T) {
|
||||||
// Initially should be empty
|
// Initially should be empty
|
||||||
rr := h.makeRequest(t, http.MethodGet, baseURL+"/last", nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, baseURL+"/last", nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var response struct {
|
var response struct {
|
||||||
@@ -170,11 +170,11 @@ func TestFileHandlers_Integration(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
FilePath: "docs/readme.md",
|
FilePath: "docs/readme.md",
|
||||||
}
|
}
|
||||||
rr = h.makeRequest(t, http.MethodPut, baseURL+"/last", updateReq, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodPut, baseURL+"/last", updateReq, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusNoContent, rr.Code)
|
require.Equal(t, http.StatusNoContent, rr.Code)
|
||||||
|
|
||||||
// Verify update
|
// Verify update
|
||||||
rr = h.makeRequest(t, http.MethodGet, baseURL+"/last", nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, baseURL+"/last", nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
err = json.NewDecoder(rr.Body).Decode(&response)
|
err = json.NewDecoder(rr.Body).Decode(&response)
|
||||||
@@ -183,7 +183,7 @@ func TestFileHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
// Test invalid file path
|
// Test invalid file path
|
||||||
updateReq.FilePath = "nonexistent.md"
|
updateReq.FilePath = "nonexistent.md"
|
||||||
rr = h.makeRequest(t, http.MethodPut, baseURL+"/last", updateReq, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodPut, baseURL+"/last", updateReq, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -204,12 +204,12 @@ func TestFileHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
// Test without token
|
// Test without session
|
||||||
rr := h.makeRequest(t, tc.method, tc.path, tc.body, "", nil)
|
rr := h.makeRequest(t, tc.method, tc.path, tc.body, nil, nil)
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||||
|
|
||||||
// Test with wrong user's token
|
// Test with wrong user's session
|
||||||
rr = h.makeRequest(t, tc.method, tc.path, tc.body, h.AdminToken, nil)
|
rr = h.makeRequest(t, tc.method, tc.path, tc.body, h.AdminSession, nil)
|
||||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -226,11 +226,11 @@ func TestFileHandlers_Integration(t *testing.T) {
|
|||||||
for _, path := range maliciousPaths {
|
for _, path := range maliciousPaths {
|
||||||
t.Run(path, func(t *testing.T) {
|
t.Run(path, func(t *testing.T) {
|
||||||
// Try to read
|
// Try to read
|
||||||
rr := h.makeRequest(t, http.MethodGet, baseURL+"/"+path, nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, baseURL+"/"+path, nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
||||||
|
|
||||||
// Try to write
|
// Try to write
|
||||||
rr = h.makeRequest(t, http.MethodPost, baseURL+"/"+path, "malicious content", h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodPost, baseURL+"/"+path, "malicious content", h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func TestGitHandlers_Integration(t *testing.T) {
|
|||||||
GitCommitMsgTemplate: "Update: {{message}}",
|
GitCommitMsgTemplate: "Update: {{message}}",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
err := json.NewDecoder(rr.Body).Decode(workspace)
|
err := json.NewDecoder(rr.Body).Decode(workspace)
|
||||||
@@ -50,7 +50,7 @@ func TestGitHandlers_Integration(t *testing.T) {
|
|||||||
"message": commitMsg,
|
"message": commitMsg,
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, baseURL+"/commit", requestBody, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, baseURL+"/commit", requestBody, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var response map[string]string
|
var response map[string]string
|
||||||
@@ -70,7 +70,7 @@ func TestGitHandlers_Integration(t *testing.T) {
|
|||||||
"message": "",
|
"message": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, baseURL+"/commit", requestBody, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, baseURL+"/commit", requestBody, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
||||||
assert.Equal(t, 0, h.MockGit.GetCommitCount(), "Commit should not be called")
|
assert.Equal(t, 0, h.MockGit.GetCommitCount(), "Commit should not be called")
|
||||||
})
|
})
|
||||||
@@ -83,7 +83,7 @@ func TestGitHandlers_Integration(t *testing.T) {
|
|||||||
"message": "Test message",
|
"message": "Test message",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, baseURL+"/commit", requestBody, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, baseURL+"/commit", requestBody, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusInternalServerError, rr.Code)
|
assert.Equal(t, http.StatusInternalServerError, rr.Code)
|
||||||
|
|
||||||
h.MockGit.SetError(nil) // Reset error state
|
h.MockGit.SetError(nil) // Reset error state
|
||||||
@@ -94,7 +94,7 @@ func TestGitHandlers_Integration(t *testing.T) {
|
|||||||
h.MockGit.Reset()
|
h.MockGit.Reset()
|
||||||
|
|
||||||
t.Run("successful pull", func(t *testing.T) {
|
t.Run("successful pull", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodPost, baseURL+"/pull", nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, baseURL+"/pull", nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var response map[string]string
|
var response map[string]string
|
||||||
@@ -109,7 +109,7 @@ func TestGitHandlers_Integration(t *testing.T) {
|
|||||||
h.MockGit.Reset()
|
h.MockGit.Reset()
|
||||||
h.MockGit.SetError(fmt.Errorf("mock git error"))
|
h.MockGit.SetError(fmt.Errorf("mock git error"))
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, baseURL+"/pull", nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, baseURL+"/pull", nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusInternalServerError, rr.Code)
|
assert.Equal(t, http.StatusInternalServerError, rr.Code)
|
||||||
|
|
||||||
h.MockGit.SetError(nil) // Reset error state
|
h.MockGit.SetError(nil) // Reset error state
|
||||||
@@ -140,12 +140,12 @@ func TestGitHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
// Test without token
|
// Test without session
|
||||||
rr := h.makeRequest(t, tc.method, tc.path, tc.body, "", nil)
|
rr := h.makeRequest(t, tc.method, tc.path, tc.body, nil, nil)
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||||
|
|
||||||
// Test with wrong user's token
|
// Test with wrong user's session
|
||||||
rr = h.makeRequest(t, tc.method, tc.path, tc.body, h.AdminToken, nil)
|
rr = h.makeRequest(t, tc.method, tc.path, tc.body, h.AdminSession, nil)
|
||||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ func TestGitHandlers_Integration(t *testing.T) {
|
|||||||
Name: "Non-Git Workspace",
|
Name: "Non-Git Workspace",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", nonGitWorkspace, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", nonGitWorkspace, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
err := json.NewDecoder(rr.Body).Decode(nonGitWorkspace)
|
err := json.NewDecoder(rr.Body).Decode(nonGitWorkspace)
|
||||||
@@ -170,11 +170,11 @@ func TestGitHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
// Try to commit
|
// Try to commit
|
||||||
commitMsg := map[string]string{"message": "test"}
|
commitMsg := map[string]string{"message": "test"}
|
||||||
rr = h.makeRequest(t, http.MethodPost, nonGitBaseURL+"/commit", commitMsg, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodPost, nonGitBaseURL+"/commit", commitMsg, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusInternalServerError, rr.Code)
|
assert.Equal(t, http.StatusInternalServerError, rr.Code)
|
||||||
|
|
||||||
// Try to pull
|
// Try to pull
|
||||||
rr = h.makeRequest(t, http.MethodPost, nonGitBaseURL+"/pull", nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodPost, nonGitBaseURL+"/pull", nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusInternalServerError, rr.Code)
|
assert.Equal(t, http.StatusInternalServerError, rr.Code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -29,10 +30,11 @@ type testHarness struct {
|
|||||||
Storage storage.Manager
|
Storage storage.Manager
|
||||||
JWTManager auth.JWTManager
|
JWTManager auth.JWTManager
|
||||||
SessionManager auth.SessionManager
|
SessionManager auth.SessionManager
|
||||||
|
CookieManager auth.CookieManager
|
||||||
AdminUser *models.User
|
AdminUser *models.User
|
||||||
AdminToken string
|
AdminSession *models.Session
|
||||||
RegularUser *models.User
|
RegularUser *models.User
|
||||||
RegularToken string
|
RegularSession *models.Session
|
||||||
TempDirectory string
|
TempDirectory string
|
||||||
MockGit *MockGitClient
|
MockGit *MockGitClient
|
||||||
}
|
}
|
||||||
@@ -86,6 +88,9 @@ func setupTestHarness(t *testing.T) *testHarness {
|
|||||||
// Initialize session service
|
// Initialize session service
|
||||||
sessionSvc := auth.NewSessionService(database, jwtSvc)
|
sessionSvc := auth.NewSessionService(database, jwtSvc)
|
||||||
|
|
||||||
|
// Initialize cookie service
|
||||||
|
cookieSvc := auth.NewCookieService(true, "localhost")
|
||||||
|
|
||||||
// Create test config
|
// Create test config
|
||||||
testConfig := &app.Config{
|
testConfig := &app.Config{
|
||||||
DBPath: ":memory:",
|
DBPath: ":memory:",
|
||||||
@@ -116,18 +121,19 @@ func setupTestHarness(t *testing.T) *testHarness {
|
|||||||
Storage: storageSvc,
|
Storage: storageSvc,
|
||||||
JWTManager: jwtSvc,
|
JWTManager: jwtSvc,
|
||||||
SessionManager: sessionSvc,
|
SessionManager: sessionSvc,
|
||||||
|
CookieManager: cookieSvc,
|
||||||
TempDirectory: tempDir,
|
TempDirectory: tempDir,
|
||||||
MockGit: mockGit,
|
MockGit: mockGit,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create test users
|
// Create test users
|
||||||
adminUser, adminToken := h.createTestUser(t, "admin@test.com", "admin123", models.RoleAdmin)
|
adminUser, adminSession := h.createTestUser(t, "admin@test.com", "admin123", models.RoleAdmin)
|
||||||
regularUser, regularToken := h.createTestUser(t, "user@test.com", "user123", models.RoleEditor)
|
regularUser, regularSession := h.createTestUser(t, "user@test.com", "user123", models.RoleEditor)
|
||||||
|
|
||||||
h.AdminUser = adminUser
|
h.AdminUser = adminUser
|
||||||
h.AdminToken = adminToken
|
h.AdminSession = adminSession
|
||||||
h.RegularUser = regularUser
|
h.RegularUser = regularUser
|
||||||
h.RegularToken = regularToken
|
h.RegularSession = regularSession
|
||||||
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
@@ -146,7 +152,7 @@ func (h *testHarness) teardown(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createTestUser creates a test user and returns the user and access token
|
// createTestUser creates a test user and returns the user and access token
|
||||||
func (h *testHarness) createTestUser(t *testing.T, email, password string, role models.UserRole) (*models.User, string) {
|
func (h *testHarness) createTestUser(t *testing.T, email, password string, role models.UserRole) (*models.User, *models.Session) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||||
@@ -172,25 +178,19 @@ func (h *testHarness) createTestUser(t *testing.T, email, password string, role
|
|||||||
t.Fatalf("Failed to initialize user workspace: %v", err)
|
t.Fatalf("Failed to initialize user workspace: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
session, accessToken, err := h.SessionManager.CreateSession(user.ID, string(user.Role))
|
session, _, err := h.SessionManager.CreateSession(user.ID, string(user.Role))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create session: %v", err)
|
t.Fatalf("Failed to create session: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if session == nil || accessToken == "" {
|
return user, session
|
||||||
t.Fatal("Failed to get valid session or token")
|
|
||||||
}
|
|
||||||
|
|
||||||
return user, accessToken
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeRequest is a helper function to make HTTP requests in tests
|
func (h *testHarness) newRequest(t *testing.T, method, path string, body interface{}) *http.Request {
|
||||||
func (h *testHarness) makeRequest(t *testing.T, method, path string, body interface{}, token string, headers map[string]string) *httptest.ResponseRecorder {
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
var reqBody []byte
|
var reqBody []byte
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if body != nil {
|
if body != nil {
|
||||||
reqBody, err = json.Marshal(body)
|
reqBody, err = json.Marshal(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -199,38 +199,87 @@ func (h *testHarness) makeRequest(t *testing.T, method, path string, body interf
|
|||||||
}
|
}
|
||||||
|
|
||||||
req := httptest.NewRequest(method, path, bytes.NewBuffer(reqBody))
|
req := httptest.NewRequest(method, path, bytes.NewBuffer(reqBody))
|
||||||
if token != "" {
|
|
||||||
req.Header.Set("Authorization", "Bearer "+token)
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
// Add any additional headers
|
// newRequestRaw creates a new request with raw body
|
||||||
for k, v := range headers {
|
func (h *testHarness) newRequestRaw(t *testing.T, method, path string, body io.Reader) *http.Request {
|
||||||
req.Header.Set(k, v)
|
t.Helper()
|
||||||
}
|
return httptest.NewRequest(method, path, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// executeRequest executes the request and returns response recorder
|
||||||
|
func (h *testHarness) executeRequest(req *http.Request) *httptest.ResponseRecorder {
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
h.Server.Router().ServeHTTP(rr, req)
|
h.Server.Router().ServeHTTP(rr, req)
|
||||||
|
|
||||||
return rr
|
return rr
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeRequestRaw is a helper function to make HTTP requests with raw body content
|
// addAuthCookies adds authentication cookies to request
|
||||||
func (h *testHarness) makeRequestRaw(t *testing.T, method, path string, body io.Reader, token string, headers map[string]string) *httptest.ResponseRecorder {
|
func (h *testHarness) addAuthCookies(t *testing.T, req *http.Request, session *models.Session, addCSRF bool) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
req := httptest.NewRequest(method, path, body)
|
if session == nil {
|
||||||
if token != "" {
|
return ""
|
||||||
req.Header.Set("Authorization", "Bearer "+token)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any additional headers
|
accessToken, err := h.JWTManager.GenerateAccessToken(session.UserID, "admin")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to generate access token: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.AddCookie(h.CookieManager.GenerateAccessTokenCookie(accessToken))
|
||||||
|
req.AddCookie(h.CookieManager.GenerateRefreshTokenCookie(session.RefreshToken))
|
||||||
|
|
||||||
|
if addCSRF {
|
||||||
|
csrfToken := "test-csrf-token"
|
||||||
|
req.AddCookie(h.CookieManager.GenerateCSRFCookie(csrfToken))
|
||||||
|
return csrfToken
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeRequest is the main helper for making JSON requests
|
||||||
|
func (h *testHarness) makeRequest(t *testing.T, method, path string, body interface{}, session *models.Session, headers map[string]string) *httptest.ResponseRecorder {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
req := h.newRequest(t, method, path, body)
|
||||||
|
|
||||||
|
// Add custom headers
|
||||||
for k, v := range headers {
|
for k, v := range headers {
|
||||||
req.Header.Set(k, v)
|
req.Header.Set(k, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
if session != nil {
|
||||||
h.Server.Router().ServeHTTP(rr, req)
|
needsCSRF := method != http.MethodGet && method != http.MethodHead && method != http.MethodOptions
|
||||||
|
csrfToken := h.addAuthCookies(t, req, session, needsCSRF)
|
||||||
|
if needsCSRF {
|
||||||
|
req.Header.Set("X-CSRF-Token", csrfToken)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return rr
|
return h.executeRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeRequestRawWithHeaders adds support for custom headers with raw body
|
||||||
|
func (h *testHarness) makeRequestRaw(t *testing.T, method, path string, body io.Reader, session *models.Session, headers map[string]string) *httptest.ResponseRecorder {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
req := h.newRequestRaw(t, method, path, body)
|
||||||
|
|
||||||
|
// Add custom headers
|
||||||
|
for k, v := range headers {
|
||||||
|
req.Header.Set(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if session != nil {
|
||||||
|
needsCSRF := method != http.MethodGet && method != http.MethodHead && method != http.MethodOptions
|
||||||
|
csrfToken := h.addAuthCookies(t, req, session, needsCSRF)
|
||||||
|
if needsCSRF {
|
||||||
|
req.Header.Set("X-CSRF-Token", csrfToken)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.executeRequest(req)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("get current user", func(t *testing.T) {
|
t.Run("get current user", func(t *testing.T) {
|
||||||
t.Run("successful get", func(t *testing.T) {
|
t.Run("successful get", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodGet, "/api/v1/auth/me", nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, "/api/v1/auth/me", nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var user models.User
|
var user models.User
|
||||||
@@ -38,7 +38,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("unauthorized", func(t *testing.T) {
|
t.Run("unauthorized", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodGet, "/api/v1/auth/me", nil, "", nil)
|
rr := h.makeRequest(t, http.MethodGet, "/api/v1/auth/me", nil, nil, nil)
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -49,7 +49,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
DisplayName: "Updated Name",
|
DisplayName: "Updated Name",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var user models.User
|
var user models.User
|
||||||
@@ -64,7 +64,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
CurrentPassword: currentPassword,
|
CurrentPassword: currentPassword,
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var user models.User
|
var user models.User
|
||||||
@@ -80,7 +80,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
Email: "anotheremail@test.com",
|
Email: "anotheremail@test.com",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
CurrentPassword: "wrongpassword",
|
CurrentPassword: "wrongpassword",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
NewPassword: "newpassword123",
|
NewPassword: "newpassword123",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
// Verify can login with new password
|
// Verify can login with new password
|
||||||
@@ -109,7 +109,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
Password: "newpassword123",
|
Password: "newpassword123",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr = h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", loginReq, "", nil)
|
rr = h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", loginReq, nil, nil)
|
||||||
assert.Equal(t, http.StatusOK, rr.Code)
|
assert.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
currentPassword = updateReq.NewPassword
|
currentPassword = updateReq.NewPassword
|
||||||
@@ -120,7 +120,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
NewPassword: "newpass123",
|
NewPassword: "newpass123",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
NewPassword: "newpass123",
|
NewPassword: "newpass123",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
NewPassword: "short",
|
NewPassword: "short",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
CurrentPassword: currentPassword,
|
CurrentPassword: currentPassword,
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, "/api/v1/profile", updateReq, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusConflict, rr.Code)
|
assert.Equal(t, http.StatusConflict, rr.Code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -164,37 +164,44 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
Role: models.RoleEditor,
|
Role: models.RoleEditor,
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", createReq, h.AdminToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/admin/users", createReq, h.AdminSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var newUser models.User
|
var newUser models.User
|
||||||
err := json.NewDecoder(rr.Body).Decode(&newUser)
|
err := json.NewDecoder(rr.Body).Decode(&newUser)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Get token for new user
|
// Get session for new user
|
||||||
loginReq := handlers.LoginRequest{
|
loginReq := handlers.LoginRequest{
|
||||||
Email: createReq.Email,
|
Email: createReq.Email,
|
||||||
Password: createReq.Password,
|
Password: createReq.Password,
|
||||||
}
|
}
|
||||||
|
|
||||||
rr = h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", loginReq, "", nil)
|
rr = h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", loginReq, nil, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var loginResp handlers.LoginResponse
|
var loginResp handlers.LoginResponse
|
||||||
err = json.NewDecoder(rr.Body).Decode(&loginResp)
|
err = json.NewDecoder(rr.Body).Decode(&loginResp)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
userToken := loginResp.AccessToken
|
|
||||||
|
// Create a session struct for the new user
|
||||||
|
userSession := &models.Session{
|
||||||
|
ID: loginResp.SessionID,
|
||||||
|
UserID: newUser.ID,
|
||||||
|
RefreshToken: "",
|
||||||
|
ExpiresAt: loginResp.ExpiresAt,
|
||||||
|
}
|
||||||
|
|
||||||
t.Run("successful delete", func(t *testing.T) {
|
t.Run("successful delete", func(t *testing.T) {
|
||||||
deleteReq := handlers.DeleteAccountRequest{
|
deleteReq := handlers.DeleteAccountRequest{
|
||||||
Password: createReq.Password,
|
Password: createReq.Password,
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/profile", deleteReq, userToken, nil)
|
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/profile", deleteReq, userSession, nil)
|
||||||
require.Equal(t, http.StatusNoContent, rr.Code)
|
require.Equal(t, http.StatusNoContent, rr.Code)
|
||||||
|
|
||||||
// Verify user is deleted
|
// Verify user is deleted
|
||||||
rr = h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", loginReq, "", nil)
|
rr = h.makeRequest(t, http.MethodPost, "/api/v1/auth/login", loginReq, nil, nil)
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -203,7 +210,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
Password: "wrongpassword",
|
Password: "wrongpassword",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/profile", deleteReq, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/profile", deleteReq, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -212,7 +219,7 @@ func TestUserHandlers_Integration(t *testing.T) {
|
|||||||
Password: "admin123", // Admin password from test harness
|
Password: "admin123", // Admin password from test harness
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/profile", deleteReq, h.AdminToken, nil)
|
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/profile", deleteReq, h.AdminSession, nil)
|
||||||
assert.Equal(t, http.StatusForbidden, rr.Code)
|
assert.Equal(t, http.StatusForbidden, rr.Code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("list workspaces", func(t *testing.T) {
|
t.Run("list workspaces", func(t *testing.T) {
|
||||||
t.Run("successful list", func(t *testing.T) {
|
t.Run("successful list", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodGet, "/api/v1/workspaces", nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, "/api/v1/workspaces", nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var workspaces []*models.Workspace
|
var workspaces []*models.Workspace
|
||||||
@@ -30,7 +30,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("unauthorized", func(t *testing.T) {
|
t.Run("unauthorized", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodGet, "/api/v1/workspaces", nil, "", nil)
|
rr := h.makeRequest(t, http.MethodGet, "/api/v1/workspaces", nil, nil, nil)
|
||||||
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
assert.Equal(t, http.StatusUnauthorized, rr.Code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -41,7 +41,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
Name: "Test Workspace",
|
Name: "Test Workspace",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var created models.Workspace
|
var created models.Workspace
|
||||||
@@ -64,7 +64,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
GitCommitEmail: "test@example.com",
|
GitCommitEmail: "test@example.com",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var created models.Workspace
|
var created models.Workspace
|
||||||
@@ -86,7 +86,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
// Missing required Git settings
|
// Missing required Git settings
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -95,7 +95,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
workspace := &models.Workspace{
|
workspace := &models.Workspace{
|
||||||
Name: "Test Workspace Operations",
|
Name: "Test Workspace Operations",
|
||||||
}
|
}
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
err := json.NewDecoder(rr.Body).Decode(workspace)
|
err := json.NewDecoder(rr.Body).Decode(workspace)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -105,7 +105,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("get workspace", func(t *testing.T) {
|
t.Run("get workspace", func(t *testing.T) {
|
||||||
t.Run("successful get", func(t *testing.T) {
|
t.Run("successful get", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodGet, baseURL, nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, baseURL, nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var got models.Workspace
|
var got models.Workspace
|
||||||
@@ -116,13 +116,13 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("nonexistent workspace", func(t *testing.T) {
|
t.Run("nonexistent workspace", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodGet, "/api/v1/workspaces/nonexistent", nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, "/api/v1/workspaces/nonexistent", nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("unauthorized access", func(t *testing.T) {
|
t.Run("unauthorized access", func(t *testing.T) {
|
||||||
// Try accessing with another user's token
|
// Try accessing with another user's token
|
||||||
rr := h.makeRequest(t, http.MethodGet, baseURL, nil, h.AdminToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, baseURL, nil, h.AdminSession, nil)
|
||||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -131,7 +131,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
t.Run("update name", func(t *testing.T) {
|
t.Run("update name", func(t *testing.T) {
|
||||||
workspace.Name = "Updated Workspace"
|
workspace.Name = "Updated Workspace"
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, baseURL, workspace, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, baseURL, workspace, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var updated models.Workspace
|
var updated models.Workspace
|
||||||
@@ -152,7 +152,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
ShowHiddenFiles: true,
|
ShowHiddenFiles: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, baseURL, update, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, baseURL, update, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var updated models.Workspace
|
var updated models.Workspace
|
||||||
@@ -176,7 +176,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
GitCommitEmail: "test@example.com",
|
GitCommitEmail: "test@example.com",
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, baseURL, update, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, baseURL, update, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var updated models.Workspace
|
var updated models.Workspace
|
||||||
@@ -200,14 +200,14 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
// Missing required Git settings
|
// Missing required Git settings
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, baseURL, update, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, baseURL, update, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("last workspace", func(t *testing.T) {
|
t.Run("last workspace", func(t *testing.T) {
|
||||||
t.Run("get last workspace", func(t *testing.T) {
|
t.Run("get last workspace", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodGet, "/api/v1/workspaces/last", nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, "/api/v1/workspaces/last", nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var response struct {
|
var response struct {
|
||||||
@@ -225,11 +225,11 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
WorkspaceName: workspace.Name,
|
WorkspaceName: workspace.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := h.makeRequest(t, http.MethodPut, "/api/v1/workspaces/last", req, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPut, "/api/v1/workspaces/last", req, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusNoContent, rr.Code)
|
require.Equal(t, http.StatusNoContent, rr.Code)
|
||||||
|
|
||||||
// Verify the update
|
// Verify the update
|
||||||
rr = h.makeRequest(t, http.MethodGet, "/api/v1/workspaces/last", nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, "/api/v1/workspaces/last", nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var response struct {
|
var response struct {
|
||||||
@@ -243,7 +243,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("delete workspace", func(t *testing.T) {
|
t.Run("delete workspace", func(t *testing.T) {
|
||||||
// Get current workspaces to know how many we have
|
// Get current workspaces to know how many we have
|
||||||
rr := h.makeRequest(t, http.MethodGet, "/api/v1/workspaces", nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodGet, "/api/v1/workspaces", nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var existingWorkspaces []*models.Workspace
|
var existingWorkspaces []*models.Workspace
|
||||||
@@ -254,13 +254,13 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
newWorkspace := &models.Workspace{
|
newWorkspace := &models.Workspace{
|
||||||
Name: "Workspace To Delete",
|
Name: "Workspace To Delete",
|
||||||
}
|
}
|
||||||
rr = h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", newWorkspace, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", newWorkspace, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
err = json.NewDecoder(rr.Body).Decode(newWorkspace)
|
err = json.NewDecoder(rr.Body).Decode(newWorkspace)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("successful delete", func(t *testing.T) {
|
t.Run("successful delete", func(t *testing.T) {
|
||||||
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/workspaces/"+url.PathEscape(newWorkspace.Name), nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/workspaces/"+url.PathEscape(newWorkspace.Name), nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
var response struct {
|
var response struct {
|
||||||
@@ -271,7 +271,7 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
assert.NotEmpty(t, response.NextWorkspaceName)
|
assert.NotEmpty(t, response.NextWorkspaceName)
|
||||||
|
|
||||||
// Verify workspace is deleted
|
// Verify workspace is deleted
|
||||||
rr = h.makeRequest(t, http.MethodGet, "/api/v1/workspaces/"+url.PathEscape(newWorkspace.Name), nil, h.RegularToken, nil)
|
rr = h.makeRequest(t, http.MethodGet, "/api/v1/workspaces/"+url.PathEscape(newWorkspace.Name), nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -279,13 +279,13 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
// Delete all but one workspace
|
// Delete all but one workspace
|
||||||
for i := 0; i < len(existingWorkspaces)-1; i++ {
|
for i := 0; i < len(existingWorkspaces)-1; i++ {
|
||||||
ws := existingWorkspaces[i]
|
ws := existingWorkspaces[i]
|
||||||
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/workspaces/"+url.PathEscape(ws.Name), nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/workspaces/"+url.PathEscape(ws.Name), nil, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to delete the last remaining workspace
|
// Try to delete the last remaining workspace
|
||||||
lastWs := existingWorkspaces[len(existingWorkspaces)-1]
|
lastWs := existingWorkspaces[len(existingWorkspaces)-1]
|
||||||
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/workspaces/"+url.PathEscape(lastWs.Name), nil, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodDelete, "/api/v1/workspaces/"+url.PathEscape(lastWs.Name), nil, h.RegularSession, nil)
|
||||||
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
assert.Equal(t, http.StatusBadRequest, rr.Code)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -294,11 +294,11 @@ func TestWorkspaceHandlers_Integration(t *testing.T) {
|
|||||||
workspace := &models.Workspace{
|
workspace := &models.Workspace{
|
||||||
Name: "Unauthorized Delete Test",
|
Name: "Unauthorized Delete Test",
|
||||||
}
|
}
|
||||||
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularToken, nil)
|
rr := h.makeRequest(t, http.MethodPost, "/api/v1/workspaces", workspace, h.RegularSession, nil)
|
||||||
require.Equal(t, http.StatusOK, rr.Code)
|
require.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
// Try to delete with wrong user's token
|
// Try to delete with wrong user's token
|
||||||
rr = h.makeRequest(t, http.MethodDelete, "/api/v1/workspaces/"+url.PathEscape(workspace.Name), nil, h.AdminToken, nil)
|
rr = h.makeRequest(t, http.MethodDelete, "/api/v1/workspaces/"+url.PathEscape(workspace.Name), nil, h.AdminSession, nil)
|
||||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user