chore: build
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
package orders
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"backend/internal/platform/middleware"
|
||||
)
|
||||
|
||||
// SettingsProvider and VerificationChecker are defined on the consumer
|
||||
// side (this package), matching ProductFinder/UnitFinder/PriceResolver
|
||||
// above: orders never imports the site or customerverification packages
|
||||
// directly, main.go just needs to supply something satisfying these shapes.
|
||||
type SettingsProvider interface {
|
||||
CustomerCheckoutSettings(ctx context.Context) (accountsEnabled, verificationRequired bool, err error)
|
||||
}
|
||||
|
||||
type VerificationChecker interface {
|
||||
IsApproved(ctx context.Context, userID uuid.UUID) (bool, error)
|
||||
}
|
||||
|
||||
// OrdersGate reports the site-wide "vitrine vs boutique" switch
|
||||
// (site.Settings.OrdersEnabled). It runs before every other order gate: a
|
||||
// pure showcase site rejects order creation outright, regardless of the
|
||||
// customer-account settings below.
|
||||
type OrdersGate interface {
|
||||
OrdersEnabled(ctx context.Context) (bool, error)
|
||||
}
|
||||
|
||||
// RequireOrdersEnabled blocks order creation entirely while the admin has
|
||||
// switched the site to showcase-only mode.
|
||||
func RequireOrdersEnabled(gate OrdersGate) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
enabled, err := gate.OrdersEnabled(c.Request.Context())
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to check orders setting"})
|
||||
return
|
||||
}
|
||||
if !enabled {
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "ordering is currently disabled for this shop"})
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// RequireAccountsEnabled blocks order creation entirely while the admin
|
||||
// hasn't turned on customer accounts. This is intentionally stricter than
|
||||
// "guest checkout allowed by default": some shops (e.g. selling
|
||||
// age/ID-restricted goods) need every order tied to a verified account, so
|
||||
// the admin opts into that by flipping this one setting, and until they
|
||||
// do, nobody -- guest or not -- can check out.
|
||||
func RequireAccountsEnabled(settings SettingsProvider) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
enabled, _, err := settings.CustomerCheckoutSettings(c.Request.Context())
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to check checkout settings"})
|
||||
return
|
||||
}
|
||||
if !enabled {
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "ordering requires a customer account, which is currently disabled"})
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// RequireApprovedVerificationIfNeeded must run after RequireAccountsEnabled
|
||||
// and middleware.RequireCustomer (so a userID is already in context). It is
|
||||
// a no-op unless the admin also turned on identity verification.
|
||||
func RequireApprovedVerificationIfNeeded(settings SettingsProvider, verification VerificationChecker) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
_, verificationRequired, err := settings.CustomerCheckoutSettings(c.Request.Context())
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to check checkout settings"})
|
||||
return
|
||||
}
|
||||
if !verificationRequired {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
userID, ok := middleware.GetUserID(c)
|
||||
if !ok {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
return
|
||||
}
|
||||
approved, err := verification.IsApproved(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to check verification status"})
|
||||
return
|
||||
}
|
||||
if !approved {
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "identity verification must be approved before ordering"})
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user