- CI: workflows updates (cd, ci), remove playwright.yml - E2E: global-setup, auth/playlists/profile specs - Remove playwright-report and test-results artifacts from tracking - Backend: auth, handlers, services, workers, migrations - Frontend: components, features, vite config - Add e2e-results.json to gitignore - Docs: REMEDIATION_PROGRESS, audit archive - Rust: chat-server, stream-server updates
121 lines
3.5 KiB
Go
121 lines
3.5 KiB
Go
package admin
|
|
|
|
import (
|
|
"fmt"
|
|
"veza-backend-api/internal/database"
|
|
"veza-backend-api/internal/models"
|
|
)
|
|
|
|
type Service struct {
|
|
db *database.DB
|
|
}
|
|
|
|
func NewService(db *database.DB) *Service {
|
|
return &Service{db: db}
|
|
}
|
|
|
|
func (s *Service) IsAdmin(userID int64) bool {
|
|
var role string
|
|
err := s.db.QueryRow("SELECT role FROM users WHERE id = $1", userID).Scan(&role)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return role == "admin" || role == "super_admin"
|
|
}
|
|
|
|
func (s *Service) GetDashboardStats() (*models.DashboardStats, error) {
|
|
stats := &models.DashboardStats{}
|
|
|
|
// Récupérer les statistiques
|
|
if err := s.db.QueryRow("SELECT COUNT(*) FROM users WHERE is_active = true").Scan(&stats.TotalUsers); err != nil {
|
|
// Ignorer l'erreur pour l'instant
|
|
}
|
|
if err := s.db.QueryRow("SELECT COUNT(*) FROM tracks").Scan(&stats.TotalTracks); err != nil {
|
|
// Ignorer l'erreur pour l'instant
|
|
}
|
|
if err := s.db.QueryRow("SELECT COUNT(*) FROM listings WHERE status = 'open'").Scan(&stats.ActiveListings); err != nil {
|
|
// Ignorer l'erreur pour l'instant
|
|
}
|
|
|
|
return stats, nil
|
|
}
|
|
|
|
func (s *Service) GetUsers(page, limit int, search, role string) ([]models.UserAnalytics, int, error) {
|
|
offset := (page - 1) * limit
|
|
if limit <= 0 {
|
|
limit = 20
|
|
}
|
|
|
|
baseQuery := `
|
|
SELECT u.id, u.username, u.email, u.role, u.created_at, u.last_login_at, u.is_active,
|
|
COALESCE((SELECT COUNT(*) FROM tracks t WHERE t.creator_id = u.id), 0) AS tracks_count,
|
|
0 AS listings_count, 0 AS resources_count, 0 AS messages_count, 0 AS products_count, 0 AS storage_used
|
|
FROM users u
|
|
WHERE u.deleted_at IS NULL
|
|
`
|
|
countQuery := `SELECT COUNT(*) FROM users u WHERE u.deleted_at IS NULL`
|
|
|
|
var whereClause string
|
|
var args []interface{}
|
|
argIndex := 1
|
|
|
|
if search != "" {
|
|
whereClause = fmt.Sprintf(` AND (u.email ILIKE $%d OR u.username ILIKE $%d OR u.first_name ILIKE $%d OR u.last_name ILIKE $%d)`, argIndex, argIndex, argIndex, argIndex)
|
|
args = append(args, "%"+search+"%")
|
|
argIndex++
|
|
}
|
|
if role != "" {
|
|
whereClause += fmt.Sprintf(` AND u.role = $%d`, argIndex)
|
|
args = append(args, role)
|
|
argIndex++
|
|
}
|
|
|
|
// Get total count
|
|
var total int
|
|
err := s.db.QueryRow(countQuery+whereClause, args...).Scan(&total)
|
|
if err != nil {
|
|
return nil, 0, fmt.Errorf("failed to count users: %w", err)
|
|
}
|
|
|
|
// Get users with pagination
|
|
orderClause := " ORDER BY u.created_at DESC"
|
|
limitClause := fmt.Sprintf(" LIMIT $%d OFFSET $%d", argIndex, argIndex+1)
|
|
args = append(args, limit, offset)
|
|
|
|
query := baseQuery + whereClause + orderClause + limitClause
|
|
rows, err := s.db.Query(query, args...)
|
|
if err != nil {
|
|
return nil, 0, fmt.Errorf("failed to query users: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var users []models.UserAnalytics
|
|
for rows.Next() {
|
|
var u models.UserAnalytics
|
|
err := rows.Scan(
|
|
&u.UserID, &u.Username, &u.Email, &u.Role, &u.RegistrationDate, &u.LastActivity, &u.IsActive,
|
|
&u.TracksCount, &u.ListingsCount, &u.ResourcesCount, &u.MessagesCount, &u.ProductsCount, &u.StorageUsed,
|
|
)
|
|
if err != nil {
|
|
return nil, 0, fmt.Errorf("failed to scan user: %w", err)
|
|
}
|
|
users = append(users, u)
|
|
}
|
|
|
|
return users, total, nil
|
|
}
|
|
|
|
func (s *Service) GetAnalytics() (*models.AdminContentAnalytics, error) {
|
|
return &models.AdminContentAnalytics{
|
|
TracksByMonth: []models.MonthlyCount{},
|
|
ResourcesByMonth: []models.MonthlyCount{},
|
|
UsersByMonth: []models.MonthlyCount{},
|
|
PopularTags: []models.TagCount{},
|
|
TopUploaders: []models.UploaderStats{},
|
|
CategoryStats: []models.CategoryStats{},
|
|
}, nil
|
|
}
|
|
|
|
func (s *Service) GetCategories() ([]interface{}, error) {
|
|
return []interface{}{}, nil
|
|
}
|