init push

This commit is contained in:
2026-07-16 22:16:45 +07:00
commit 8b068bdb10
1021 changed files with 332816 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
package middleware
import (
"github.com/gofiber/fiber/v2"
"wucher/internal/service"
sharedconst "wucher/internal/shared/const"
"wucher/internal/shared/pkg/apperrorsx"
)
const permissionPinVerificationHeader = "X-PIN-Verification-Token"
func PermissionRequired(svc *service.AuthService, permissionKey string) fiber.Handler {
return permissionRequired(svc, permissionKey, true)
}
func PermissionRequiredReusable(svc *service.AuthService, permissionKey string) fiber.Handler {
return permissionRequired(svc, permissionKey, false)
}
func permissionRequired(svc *service.AuthService, permissionKey string, consume bool) fiber.Handler {
return func(c *fiber.Ctx) error {
if svc == nil {
e := apperrorsx.New(apperrorsx.ErrUserUnauthorized)
e.Message = "auth service not configured"
return apperrorsx.Write(c, e)
}
raw := c.Locals("user_id")
userID, ok := raw.([]byte)
if !ok || len(userID) == 0 {
e := apperrorsx.New(apperrorsx.ErrUserUnauthorized)
e.Message = "missing auth context"
return apperrorsx.Write(c, e)
}
allowed, err := svc.HasPermission(c.UserContext(), userID, permissionKey)
if err != nil {
e := apperrorsx.New(apperrorsx.ErrForbiddenAccess)
e.Message = "failed to verify permission"
return apperrorsx.Write(c, e)
}
if !allowed {
e := apperrorsx.New(apperrorsx.ErrForbiddenAccess)
e.Message = "insufficient permission"
return apperrorsx.Write(c, e)
}
required, err := svc.PermissionRequiresPIN(c.UserContext(), permissionKey)
if err != nil {
e := apperrorsx.New(apperrorsx.ErrForbiddenAccess)
e.Message = "failed to verify PIN requirement"
return apperrorsx.Write(c, e)
}
if required {
action := sharedconst.PinActionForPermissionKey(permissionKey)
if action == "" {
action = permissionKey
}
token := c.Get(permissionPinVerificationHeader)
sessionID := ""
for _, accessToken := range service.CookieValues(c.Get(fiber.HeaderCookie), svc.AccessCookieName()) {
sid, err := svc.ParseAccessTokenSessionID(c.UserContext(), accessToken)
if err == nil {
sessionID = sid
break
}
}
if sessionID == "" {
return apperrorsx.Write(c, apperrorsx.New(apperrorsx.ErrTokenInvalid))
}
var verifyErr error
if consume {
verifyErr = svc.ConsumeSecurityPINActionTokenInSession(c.UserContext(), userID, action, token, sessionID)
} else {
verifyErr = svc.ValidateSecurityPINActionTokenInSession(c.UserContext(), userID, action, token, sessionID)
}
if verifyErr != nil {
return apperrorsx.Write(c, apperrorsx.New(apperrorsx.ErrPINVerificationRequired202))
}
}
return c.Next()
}
}