283 lines
9 KiB
Go
283 lines
9 KiB
Go
package middleware
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"veza-backend-api/internal/models"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// MockPlaylistService est un mock du PlaylistService pour les tests
|
|
type MockPlaylistService struct {
|
|
mock.Mock
|
|
}
|
|
|
|
func (m *MockPlaylistService) CheckPermission(ctx context.Context, playlistID, userID int64, requiredPermission models.PlaylistPermission) (bool, error) {
|
|
args := m.Called(ctx, playlistID, userID, requiredPermission)
|
|
return args.Bool(0), args.Error(1)
|
|
}
|
|
|
|
// setupPlaylistPermissionTestRouter crée un router de test avec le middleware de permissions
|
|
func setupPlaylistPermissionTestRouter(t *testing.T) (*gin.Engine, *MockPlaylistService, func()) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
// Setup mock service
|
|
mockService := new(MockPlaylistService)
|
|
|
|
// Setup router
|
|
router := gin.New()
|
|
router.Use(func(c *gin.Context) {
|
|
// Mock authentication middleware - set user_id from query param
|
|
if userID := c.Query("user_id"); userID != "" {
|
|
var uid int64
|
|
_, err := fmt.Sscanf(userID, "%d", &uid)
|
|
if err == nil {
|
|
c.Set("user_id", uid)
|
|
}
|
|
}
|
|
c.Next()
|
|
})
|
|
|
|
// Test endpoint
|
|
router.GET("/test/:id", CheckPlaylistPermission(mockService, models.PlaylistPermissionRead), func(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{"message": "success"})
|
|
})
|
|
|
|
cleanup := func() {
|
|
// Nothing to cleanup
|
|
}
|
|
|
|
return router, mockService, cleanup
|
|
}
|
|
|
|
func TestCheckPlaylistPermission_Owner(t *testing.T) {
|
|
router, mockService, cleanup := setupPlaylistPermissionTestRouter(t)
|
|
defer cleanup()
|
|
|
|
mockService.On("CheckPermission", mock.Anything, int64(1), int64(1), models.PlaylistPermissionRead).Return(true, nil)
|
|
|
|
w := httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", "/test/1?user_id=1", nil)
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
var response map[string]string
|
|
json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.Equal(t, "success", response["message"])
|
|
mockService.AssertExpectations(t)
|
|
}
|
|
|
|
func TestCheckPlaylistPermission_PublicRead(t *testing.T) {
|
|
router, mockService, cleanup := setupPlaylistPermissionTestRouter(t)
|
|
defer cleanup()
|
|
|
|
mockService.On("CheckPermission", mock.Anything, int64(1), int64(2), models.PlaylistPermissionRead).Return(true, nil)
|
|
|
|
w := httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", "/test/1?user_id=2", nil)
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
var response map[string]string
|
|
json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.Equal(t, "success", response["message"])
|
|
mockService.AssertExpectations(t)
|
|
}
|
|
|
|
func TestCheckPlaylistPermission_PrivateForbidden(t *testing.T) {
|
|
router, mockService, cleanup := setupPlaylistPermissionTestRouter(t)
|
|
defer cleanup()
|
|
|
|
mockService.On("CheckPermission", mock.Anything, int64(1), int64(2), models.PlaylistPermissionRead).Return(false, nil)
|
|
|
|
w := httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", "/test/1?user_id=2", nil)
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusForbidden, w.Code)
|
|
var response map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
require.NoError(t, err)
|
|
// P0: Nouveau format AppError
|
|
errorObj, ok := response["error"].(map[string]interface{})
|
|
require.True(t, ok, "Error should be a map")
|
|
assert.Contains(t, errorObj["message"].(string), "forbidden")
|
|
mockService.AssertExpectations(t)
|
|
}
|
|
|
|
func TestCheckPlaylistPermission_CollaboratorRead(t *testing.T) {
|
|
router, mockService, cleanup := setupPlaylistPermissionTestRouter(t)
|
|
defer cleanup()
|
|
|
|
mockService.On("CheckPermission", mock.Anything, int64(1), int64(2), models.PlaylistPermissionRead).Return(true, nil)
|
|
|
|
w := httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", "/test/1?user_id=2", nil)
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
var response map[string]string
|
|
json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.Equal(t, "success", response["message"])
|
|
mockService.AssertExpectations(t)
|
|
}
|
|
|
|
func TestCheckPlaylistPermission_CollaboratorWrite(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
mockService := new(MockPlaylistService)
|
|
mockService.On("CheckPermission", mock.Anything, int64(1), int64(2), models.PlaylistPermissionWrite).Return(true, nil)
|
|
|
|
routerWrite := gin.New()
|
|
routerWrite.Use(func(c *gin.Context) {
|
|
if userID := c.Query("user_id"); userID != "" {
|
|
var uid int64
|
|
_, err := fmt.Sscanf(userID, "%d", &uid)
|
|
if err == nil {
|
|
c.Set("user_id", uid)
|
|
}
|
|
}
|
|
c.Next()
|
|
})
|
|
routerWrite.GET("/test/:id", RequirePlaylistWrite(mockService), func(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{"message": "success"})
|
|
})
|
|
|
|
w := httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", "/test/1?user_id=2", nil)
|
|
routerWrite.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
mockService.AssertExpectations(t)
|
|
}
|
|
|
|
func TestCheckPlaylistPermission_CollaboratorReadCannotWrite(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
mockService := new(MockPlaylistService)
|
|
mockService.On("CheckPermission", mock.Anything, int64(1), int64(2), models.PlaylistPermissionWrite).Return(false, nil)
|
|
|
|
routerWrite := gin.New()
|
|
routerWrite.Use(func(c *gin.Context) {
|
|
if userID := c.Query("user_id"); userID != "" {
|
|
var uid int64
|
|
_, err := fmt.Sscanf(userID, "%d", &uid)
|
|
if err == nil {
|
|
c.Set("user_id", uid)
|
|
}
|
|
}
|
|
c.Next()
|
|
})
|
|
routerWrite.GET("/test/:id", RequirePlaylistWrite(mockService), func(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{"message": "success"})
|
|
})
|
|
|
|
w := httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", "/test/1?user_id=2", nil)
|
|
routerWrite.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusForbidden, w.Code)
|
|
mockService.AssertExpectations(t)
|
|
}
|
|
|
|
func TestCheckPlaylistPermission_NotFound(t *testing.T) {
|
|
router, mockService, cleanup := setupPlaylistPermissionTestRouter(t)
|
|
defer cleanup()
|
|
|
|
mockService.On("CheckPermission", mock.Anything, int64(99999), int64(1), models.PlaylistPermissionRead).Return(false, fmt.Errorf("playlist not found"))
|
|
|
|
w := httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", "/test/99999?user_id=1", nil)
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusNotFound, w.Code)
|
|
var response map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
require.NoError(t, err)
|
|
// P0: Nouveau format AppError
|
|
errorObj, ok := response["error"].(map[string]interface{})
|
|
require.True(t, ok, "Error should be a map")
|
|
assert.Contains(t, errorObj["message"].(string), "playlist not found")
|
|
mockService.AssertExpectations(t)
|
|
}
|
|
|
|
func TestCheckPlaylistPermission_Unauthorized(t *testing.T) {
|
|
router, mockService, cleanup := setupPlaylistPermissionTestRouter(t)
|
|
defer cleanup()
|
|
|
|
w := httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", "/test/1", nil) // Pas de user_id
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
|
var response map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
require.NoError(t, err)
|
|
// P0: Nouveau format AppError
|
|
errorObj, ok := response["error"].(map[string]interface{})
|
|
require.True(t, ok, "Error should be a map")
|
|
assert.Contains(t, errorObj["message"].(string), "unauthorized")
|
|
mockService.AssertNotCalled(t, "CheckPermission")
|
|
}
|
|
|
|
func TestCheckPlaylistPermission_InvalidPlaylistID(t *testing.T) {
|
|
router, mockService, cleanup := setupPlaylistPermissionTestRouter(t)
|
|
defer cleanup()
|
|
|
|
w := httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", "/test/invalid?user_id=1", nil)
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
var response map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
require.NoError(t, err)
|
|
// P0: Nouveau format AppError
|
|
errorObj, ok := response["error"].(map[string]interface{})
|
|
require.True(t, ok, "Error should be a map")
|
|
assert.Contains(t, errorObj["message"].(string), "invalid playlist id")
|
|
mockService.AssertNotCalled(t, "CheckPermission")
|
|
}
|
|
|
|
func TestRequirePlaylistOwner(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
mockService := new(MockPlaylistService)
|
|
mockService.On("CheckPermission", mock.Anything, int64(1), int64(1), models.PlaylistPermissionAdmin).Return(true, nil)
|
|
mockService.On("CheckPermission", mock.Anything, int64(1), int64(2), models.PlaylistPermissionAdmin).Return(false, nil)
|
|
|
|
routerOwner := gin.New()
|
|
routerOwner.Use(func(c *gin.Context) {
|
|
if userID := c.Query("user_id"); userID != "" {
|
|
var uid int64
|
|
_, err := fmt.Sscanf(userID, "%d", &uid)
|
|
if err == nil {
|
|
c.Set("user_id", uid)
|
|
}
|
|
}
|
|
c.Next()
|
|
})
|
|
routerOwner.GET("/test/:id", RequirePlaylistOwner(mockService), func(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{"message": "success"})
|
|
})
|
|
|
|
// Owner peut accéder
|
|
w := httptest.NewRecorder()
|
|
req := httptest.NewRequest("GET", "/test/1?user_id=1", nil)
|
|
routerOwner.ServeHTTP(w, req)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
// Autre utilisateur ne peut pas accéder
|
|
w2 := httptest.NewRecorder()
|
|
req2 := httptest.NewRequest("GET", "/test/1?user_id=2", nil)
|
|
routerOwner.ServeHTTP(w2, req2)
|
|
assert.Equal(t, http.StatusForbidden, w2.Code)
|
|
|
|
mockService.AssertExpectations(t)
|
|
}
|