package services import ( "context" "testing" "time" "veza-backend-api/internal/models" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/driver/sqlite" "gorm.io/gorm" ) // setupTestPermissionServiceDB crée une base de données de test pour PermissionService func setupTestPermissionServiceDB(t *testing.T) *gorm.DB { db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) require.NoError(t, err) // Enable foreign keys for SQLite db.Exec("PRAGMA foreign_keys = ON") // Create tables manually to ensure all columns exist (AutoMigrate might miss some in SQLite) db.Exec(` CREATE TABLE IF NOT EXISTS roles ( id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE, display_name TEXT NOT NULL, description TEXT, is_system INTEGER DEFAULT 0, is_active INTEGER DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `) db.Exec(` CREATE TABLE IF NOT EXISTS permissions ( id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE, resource TEXT, action TEXT, description TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `) db.Exec(` CREATE TABLE IF NOT EXISTS user_roles ( id TEXT PRIMARY KEY, user_id TEXT NOT NULL, role_id TEXT NOT NULL, role TEXT NOT NULL, assigned_at DATETIME DEFAULT CURRENT_TIMESTAMP, assigned_by TEXT, expires_at DATETIME, is_active INTEGER DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE(user_id, role) ) `) db.Exec(` CREATE TABLE IF NOT EXISTS role_permissions ( id TEXT PRIMARY KEY, role_id TEXT NOT NULL, permission_id TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE(role_id, permission_id) ) `) return db } // TestPermissionService_HasRole teste HasRole // GO-007, GO-025: Test critique pour RBAC func TestPermissionService_HasRole(t *testing.T) { db := setupTestPermissionServiceDB(t) service := NewPermissionService(db) ctx := context.Background() // Créer un rôle admin adminRole := &models.Role{ ID: uuid.New(), Name: "admin", IsActive: true, } require.NoError(t, db.Create(adminRole).Error) // Créer un rôle user userRole := &models.Role{ ID: uuid.New(), Name: "user", IsActive: true, } require.NoError(t, db.Create(userRole).Error) // Créer un utilisateur userID := uuid.New() // Test 1: Utilisateur sans rôle hasRole, err := service.HasRole(ctx, userID, "admin") require.NoError(t, err) assert.False(t, hasRole, "User without role should not have admin role") // Test 2: Utilisateur avec rôle admin userRoleRecord := &models.UserRole{ ID: uuid.New(), UserID: userID, RoleID: adminRole.ID, IsActive: true, } require.NoError(t, db.Create(userRoleRecord).Error) hasRole, err = service.HasRole(ctx, userID, "admin") require.NoError(t, err) assert.True(t, hasRole, "User with admin role should have admin role") // Test 3: Utilisateur avec rôle user (pas admin) hasRole, err = service.HasRole(ctx, userID, "user") require.NoError(t, err) assert.False(t, hasRole, "User with admin role should not have user role") // Test 4: Rôle inactif userRoleRecord.IsActive = false require.NoError(t, db.Save(userRoleRecord).Error) hasRole, err = service.HasRole(ctx, userID, "admin") require.NoError(t, err) assert.False(t, hasRole, "User with inactive role should not have role") // Test 5: Rôle expiré userRoleRecord.IsActive = true expiredTime := time.Now().Add(-1 * time.Hour) userRoleRecord.ExpiresAt = &expiredTime require.NoError(t, db.Save(userRoleRecord).Error) hasRole, err = service.HasRole(ctx, userID, "admin") require.NoError(t, err) assert.False(t, hasRole, "User with expired role should not have role") } // TestPermissionService_HasPermission teste HasPermission // GO-007, GO-025: Test critique pour RBAC func TestPermissionService_HasPermission(t *testing.T) { db := setupTestPermissionServiceDB(t) service := NewPermissionService(db) ctx := context.Background() // Créer un rôle role := &models.Role{ ID: uuid.New(), Name: "admin", IsActive: true, } require.NoError(t, db.Create(role).Error) // Créer une permission permission := &models.Permission{ ID: uuid.New(), Name: "manage_users", Resource: "users", Action: "manage", } require.NoError(t, db.Create(permission).Error) // Créer un utilisateur userID := uuid.New() // Test 1: Utilisateur sans permission hasPermission, err := service.HasPermission(ctx, userID, "manage_users") require.NoError(t, err) assert.False(t, hasPermission, "User without permission should not have permission") // Test 2: Assigner rôle à l'utilisateur userRole := &models.UserRole{ ID: uuid.New(), UserID: userID, RoleID: role.ID, IsActive: true, } require.NoError(t, db.Create(userRole).Error) // Test 3: Permission non assignée au rôle hasPermission, err = service.HasPermission(ctx, userID, "manage_users") require.NoError(t, err) assert.False(t, hasPermission, "User with role but without permission should not have permission") // Test 4: Assigner permission au rôle rolePermission := &models.RolePermission{ RoleID: role.ID, PermissionID: permission.ID, } require.NoError(t, db.Create(rolePermission).Error) hasPermission, err = service.HasPermission(ctx, userID, "manage_users") require.NoError(t, err) assert.True(t, hasPermission, "User with role and permission should have permission") // Test 5: Permission inexistante hasPermission, err = service.HasPermission(ctx, userID, "nonexistent_permission") require.NoError(t, err) assert.False(t, hasPermission, "User should not have nonexistent permission") } // TestPermissionService_GetRolePermissions teste GetRolePermissions func TestPermissionService_GetRolePermissions(t *testing.T) { db := setupTestPermissionServiceDB(t) service := NewPermissionService(db) ctx := context.Background() // Créer un rôle role := &models.Role{ ID: uuid.New(), Name: "admin", IsActive: true, } require.NoError(t, db.Create(role).Error) // Créer des permissions perm1 := &models.Permission{ ID: uuid.New(), Name: "manage_users", Resource: "users", Action: "manage", } require.NoError(t, db.Create(perm1).Error) perm2 := &models.Permission{ ID: uuid.New(), Name: "manage_tracks", Resource: "tracks", Action: "manage", } require.NoError(t, db.Create(perm2).Error) // Test 1: Rôle sans permissions permissions, err := service.GetRolePermissions(ctx, role.ID) require.NoError(t, err) assert.Empty(t, permissions, "Role without permissions should return empty list") // Test 2: Assigner permissions au rôle rolePerm1 := &models.RolePermission{ RoleID: role.ID, PermissionID: perm1.ID, } require.NoError(t, db.Create(rolePerm1).Error) rolePerm2 := &models.RolePermission{ RoleID: role.ID, PermissionID: perm2.ID, } require.NoError(t, db.Create(rolePerm2).Error) permissions, err = service.GetRolePermissions(ctx, role.ID) require.NoError(t, err) assert.Len(t, permissions, 2, "Role should have 2 permissions") } // TestPermissionService_AssignPermissionToRole teste AssignPermissionToRole func TestPermissionService_AssignPermissionToRole(t *testing.T) { db := setupTestPermissionServiceDB(t) service := NewPermissionService(db) ctx := context.Background() // Créer un rôle et une permission role := &models.Role{ ID: uuid.New(), Name: "admin", IsActive: true, } require.NoError(t, db.Create(role).Error) permission := &models.Permission{ ID: uuid.New(), Name: "manage_users", Resource: "users", Action: "manage", } require.NoError(t, db.Create(permission).Error) // Assigner permission au rôle err := service.AssignPermissionToRole(ctx, role.ID, permission.ID) require.NoError(t, err) // Vérifier que l'assignation existe var rolePermission models.RolePermission err = db.Where("role_id = ? AND permission_id = ?", role.ID, permission.ID).First(&rolePermission).Error require.NoError(t, err) assert.Equal(t, role.ID, rolePermission.RoleID) assert.Equal(t, permission.ID, rolePermission.PermissionID) } // TestPermissionService_RevokePermissionFromRole teste RevokePermissionFromRole func TestPermissionService_RevokePermissionFromRole(t *testing.T) { db := setupTestPermissionServiceDB(t) service := NewPermissionService(db) ctx := context.Background() // Créer un rôle et une permission role := &models.Role{ ID: uuid.New(), Name: "admin", IsActive: true, } require.NoError(t, db.Create(role).Error) permission := &models.Permission{ ID: uuid.New(), Name: "manage_users", Resource: "users", Action: "manage", } require.NoError(t, db.Create(permission).Error) // Assigner permission au rôle rolePermission := &models.RolePermission{ RoleID: role.ID, PermissionID: permission.ID, } require.NoError(t, db.Create(rolePermission).Error) // Révoquer permission err := service.RevokePermissionFromRole(ctx, role.ID, permission.ID) require.NoError(t, err) // Vérifier que l'assignation n'existe plus var count int64 db.Model(&models.RolePermission{}). Where("role_id = ? AND permission_id = ?", role.ID, permission.ID). Count(&count) assert.Equal(t, int64(0), count, "Permission should be revoked") // Test: Révoquer une permission inexistante err = service.RevokePermissionFromRole(ctx, role.ID, permission.ID) assert.Error(t, err, "Revoking nonexistent permission should return error") assert.Contains(t, err.Error(), "not found") }