chore: build
This commit is contained in:
@@ -137,3 +137,24 @@ func (h *Handler) AddCode(c *gin.Context) {
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": "vous passez en abonnement premium"})
|
||||
}
|
||||
|
||||
// GetPremiumUser : GET /premium — liste des clients premium (nom, date de
|
||||
// saisie du code, date de fin d'abonnement) pour l'admin.
|
||||
func (h *Handler) GetPremiumUser(c *gin.Context) {
|
||||
p := auth.PrincipalFrom(c)
|
||||
if p == nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "non authentifié"})
|
||||
return
|
||||
}
|
||||
if p.Role != "admin" {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "vous n'avez pas les droits"})
|
||||
return
|
||||
}
|
||||
|
||||
items, err := h.store.GetUserPremium()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "erreur serveur"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": items})
|
||||
}
|
||||
|
||||
@@ -15,3 +15,14 @@ type CodeBuySub struct {
|
||||
|
||||
// TableName définit explicitement le nom de la table.
|
||||
func (CodeBuySub) TableName() string { return "code_buy_subs" }
|
||||
|
||||
// PremiumUser : client actuellement en abonnement premium, tel qu'affiché
|
||||
// à l'admin sur la page des codes. ActivatedAt (date de saisie du code)
|
||||
// n'est pas stockée telle quelle — le code est supprimé une fois consommé
|
||||
// (voir Store.AddCodeForSub) — mais l'abonnement dure toujours exactement
|
||||
// PremiumDuration, donc on la déduit de ExpiredAt (voir GormStore).
|
||||
type PremiumUser struct {
|
||||
Username string `json:"username"`
|
||||
ActivatedAt time.Time `json:"activated_at"`
|
||||
ExpiredAt time.Time `json:"expired_at"`
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// PremiumDuration : durée d'un abonnement premium débloqué par un code
|
||||
// (30 jours). Sert à la fois à fixer ExpiredAt lors de l'activation et à
|
||||
// retrouver la date de saisie du code (ExpiredAt - PremiumDuration).
|
||||
const PremiumDuration = 30 * 24 * time.Hour
|
||||
|
||||
// Store définit les opérations de persistance pour les codes de souscription.
|
||||
type Store interface {
|
||||
// CreateCodeForSub crée un nouveau code pour un utilisateur.
|
||||
@@ -19,6 +24,8 @@ type Store interface {
|
||||
// ListCodes liste tous les codes.
|
||||
ListCodes() ([]CodeBuySub, error)
|
||||
AddCodeForSub(username, code string) (auth.User, error)
|
||||
// GetUserPremium liste les clients actuellement en abonnement premium.
|
||||
GetUserPremium() ([]PremiumUser, error)
|
||||
}
|
||||
|
||||
// GormStore implémente Store avec PostgreSQL via GORM.
|
||||
@@ -78,7 +85,7 @@ func (s *GormStore) AddCodeForSub(username, code string) (auth.User, error) {
|
||||
}
|
||||
|
||||
u.TypeAbo = "premium"
|
||||
u.ExpiredAt = time.Now().UTC().AddDate(0, 0, 30)
|
||||
u.ExpiredAt = time.Now().UTC().Add(PremiumDuration)
|
||||
if err := s.db.Model(&u).Updates(map[string]interface{}{
|
||||
"type_abo": u.TypeAbo,
|
||||
"expired_at": u.ExpiredAt,
|
||||
@@ -106,6 +113,25 @@ func (s *GormStore) ListCodes() ([]CodeBuySub, error) {
|
||||
return codes, nil
|
||||
}
|
||||
|
||||
// GetUserPremium liste les clients dont l'abonnement est premium, avec la
|
||||
// date de saisie du code (déduite : ExpiredAt - PremiumDuration) et la date
|
||||
// de fin d'abonnement (ExpiredAt). Trié par échéance la plus proche.
|
||||
func (s *GormStore) GetUserPremium() ([]PremiumUser, error) {
|
||||
var users []auth.User
|
||||
if err := s.db.Where("type_abo = ?", "premium").Order("expired_at asc").Find(&users).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := make([]PremiumUser, 0, len(users))
|
||||
for _, u := range users {
|
||||
out = append(out, PremiumUser{
|
||||
Username: u.Username,
|
||||
ActivatedAt: u.ExpiredAt.Add(-PremiumDuration),
|
||||
ExpiredAt: u.ExpiredAt,
|
||||
})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// MemStore implémente Store en mémoire (pour dev/tests).
|
||||
type MemStore struct {
|
||||
mu sync.RWMutex
|
||||
@@ -174,3 +200,10 @@ func (m *MemStore) AddCodeForSub(username, code string) (auth.User, error) {
|
||||
// il ne peut donc pas mettre à jour TypeAbo lui-même. Cf. point ci-dessous.
|
||||
return auth.User{Username: username, TypeAbo: "premium"}, nil
|
||||
}
|
||||
|
||||
// GetUserPremium : le MemStore (dev/tests) ne connaît pas la table des
|
||||
// utilisateurs (voir AddCodeForSub) — il ne peut donc pas lister les clients
|
||||
// premium. Renvoie une liste vide plutôt qu'une erreur.
|
||||
func (m *MemStore) GetUserPremium() ([]PremiumUser, error) {
|
||||
return []PremiumUser{}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user