LEARN_ENGLISH plans unlock LMS only; IELTS and DUOLINGO unlock matching exam-prep catalog courses. Enable category subscription gating, restrict programs to Learn English, and treat Duolingo subscriptions as non-expiring one-time purchases. Co-authored-by: Cursor <cursoragent@cursor.com>
85 lines
2.5 KiB
Go
85 lines
2.5 KiB
Go
package handlers
|
|
|
|
import (
|
|
"Yimaru-Backend/internal/domain"
|
|
"fmt"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
func (h *Handler) learnerHasSubscriptionCategory(c *fiber.Ctx, category domain.SubscriptionCategory) (bool, error) {
|
|
userID, ok := c.Locals("user_id").(int64)
|
|
if !ok || userID == 0 {
|
|
return false, fiber.NewError(fiber.StatusUnauthorized, "Unauthorized")
|
|
}
|
|
return h.subscriptionsSvc.HasActiveSubscriptionByCategory(c.Context(), userID, category)
|
|
}
|
|
|
|
func (h *Handler) ensureLearnerExamPrepContentAccess(c *fiber.Ctx, contentCategory string) error {
|
|
role, _ := c.Locals("role").(domain.Role)
|
|
if !role.IsCustomerLearnerRole() {
|
|
return nil
|
|
}
|
|
if !domain.IsExamPrepContentCategory(contentCategory) {
|
|
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
|
|
Message: "Catalog course not found",
|
|
})
|
|
}
|
|
active, err := h.learnerHasSubscriptionCategory(c, domain.SubscriptionCategory(contentCategory))
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
Message: fmt.Sprintf("Failed to verify %s subscription", contentCategory),
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
if !active {
|
|
return c.Status(fiber.StatusForbidden).JSON(domain.ErrorResponse{
|
|
Message: fmt.Sprintf("An active %s subscription is required", humanizeSubscriptionCategory(domain.SubscriptionCategory(contentCategory))),
|
|
})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (h *Handler) blockLearnerIfNotLMSProgram(c *fiber.Ctx, program domain.Program) error {
|
|
role, _ := c.Locals("role").(domain.Role)
|
|
if !role.IsCustomerLearnerRole() {
|
|
return nil
|
|
}
|
|
if !domain.IsLMSContentCategory(program.Category) {
|
|
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
|
|
Message: "Program not found",
|
|
})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func humanizeSubscriptionCategory(category domain.SubscriptionCategory) string {
|
|
switch category {
|
|
case domain.SubscriptionCategoryLearnEnglish:
|
|
return "learn english"
|
|
case domain.SubscriptionCategoryIELTS:
|
|
return "IELTS"
|
|
case domain.SubscriptionCategoryDuolingo:
|
|
return "Duolingo"
|
|
default:
|
|
return string(category)
|
|
}
|
|
}
|
|
|
|
func filterExamPrepCatalogCoursesForLearner(items []domain.ExamPrepCatalogCourse, hasIELTS, hasDuolingo bool) []domain.ExamPrepCatalogCourse {
|
|
filtered := make([]domain.ExamPrepCatalogCourse, 0, len(items))
|
|
for _, item := range items {
|
|
switch domain.SubscriptionCategory(item.Category) {
|
|
case domain.SubscriptionCategoryIELTS:
|
|
if hasIELTS {
|
|
filtered = append(filtered, item)
|
|
}
|
|
case domain.SubscriptionCategoryDuolingo:
|
|
if hasDuolingo {
|
|
filtered = append(filtered, item)
|
|
}
|
|
}
|
|
}
|
|
return filtered
|
|
}
|