subscription enforced reversed

This commit is contained in:
Yared Yemane 2026-05-27 11:40:24 -07:00
parent 2e1f9432f6
commit 8eaac9206e
3 changed files with 43 additions and 29 deletions

View File

@ -26,11 +26,6 @@ func (r Role) UsesLMSSequentialGating() bool {
return r == RoleStudent
}
// RequiresSubscription is true when paid subscription is required to access learning content.
func (r Role) RequiresSubscription() bool {
return r == RoleStudent
}
// IsCustomerLearnerRole is true for platform roles that sign in as customers and consume learner-facing LMS APIs.
func (r Role) IsCustomerLearnerRole() bool {
return r == RoleStudent || r == RoleOpenLearner

View File

@ -61,7 +61,7 @@ func (h *Handler) ListExamPrepCatalogCourses(c *fiber.Ctx) error {
offset, _ := strconv.Atoi(c.Query("offset", "0"))
role, _ := c.Locals("role").(domain.Role)
if role.RequiresSubscription() {
if role == domain.RoleStudent || role == domain.RoleOpenLearner {
userID, ok := c.Locals("user_id").(int64)
if !ok || userID == 0 {
return c.Status(fiber.StatusUnauthorized).JSON(domain.ErrorResponse{

View File

@ -15,6 +15,8 @@ import (
"go.uber.org/zap"
)
var categorySubscriptionGateDisabled = true
func (a *App) authMiddleware(c *fiber.Ctx) error {
ip := c.IP()
userAgent := c.Get("User-Agent")
@ -174,8 +176,8 @@ func (a *App) OnlyAdminAndAbove(c *fiber.Ctx) error {
return c.Next()
}
// RequireActiveSubscription enforces an active subscription for STUDENT accounts.
// Staff roles and OPEN_LEARNER bypass this check.
// RequireActiveSubscription enforces an active subscription for learner accounts.
// Staff roles (SUPER_ADMIN, ADMIN, INSTRUCTOR, SUPPORT) bypass this check.
// Use after authMiddleware on routes that deliver paid learning content.
func (a *App) RequireActiveSubscription() fiber.Handler {
return func(c *fiber.Ctx) error {
@ -183,27 +185,32 @@ func (a *App) RequireActiveSubscription() fiber.Handler {
if !ok {
return fiber.NewError(fiber.StatusForbidden, "Role not found in context")
}
if bypassSubscriptionForRole(role) || !role.RequiresSubscription() {
switch role {
case domain.RoleSuperAdmin, domain.RoleAdmin, domain.RoleInstructor, domain.RoleSupport:
return c.Next()
case domain.RoleStudent, domain.RoleOpenLearner:
userID, ok := c.Locals("user_id").(int64)
if !ok || userID == 0 {
return fiber.NewError(fiber.StatusUnauthorized, "Unauthorized")
}
active, err := a.subscriptionsSvc.HasActiveSubscription(c.Context(), userID)
if err != nil {
a.mongoLoggerSvc.Error("subscription check failed",
zap.Int64("userID", userID),
zap.String("path", c.Path()),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to verify subscription")
}
if !active {
// Temporary bypass: allow unsubscribed learners to access content.
return c.Next()
}
return c.Next()
default:
return c.Next()
}
userID, ok := c.Locals("user_id").(int64)
if !ok || userID == 0 {
return fiber.NewError(fiber.StatusUnauthorized, "Unauthorized")
}
active, err := a.subscriptionsSvc.HasActiveSubscription(c.Context(), userID)
if err != nil {
a.mongoLoggerSvc.Error("subscription check failed",
zap.Int64("userID", userID),
zap.String("path", c.Path()),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to verify subscription")
}
if !active {
return fiber.NewError(fiber.StatusForbidden, "An active subscription is required")
}
return c.Next()
}
}
@ -213,7 +220,13 @@ func (a *App) RequireSubscriptionCategory(category domain.SubscriptionCategory)
if err != nil {
return err
}
if bypassSubscriptionForRole(role) || !role.RequiresSubscription() {
if bypassSubscriptionForRole(role) {
return c.Next()
}
if role != domain.RoleStudent && role != domain.RoleOpenLearner {
return c.Next()
}
if categorySubscriptionGateDisabled {
return c.Next()
}
active, err := a.subscriptionsSvc.HasActiveSubscriptionByCategory(c.Context(), userID, category)
@ -240,7 +253,13 @@ func (a *App) RequireExamPrepSubscription() fiber.Handler {
if err != nil {
return err
}
if bypassSubscriptionForRole(role) || !role.RequiresSubscription() {
if bypassSubscriptionForRole(role) {
return c.Next()
}
if role != domain.RoleStudent && role != domain.RoleOpenLearner {
return c.Next()
}
if categorySubscriptionGateDisabled {
return c.Next()
}