add & moved to validations folder; del validator/v10

This commit is contained in:
Alex
2024-10-09 18:12:20 +02:00
parent 6aee416b63
commit b2e4947d37
12 changed files with 253 additions and 226 deletions

View File

@@ -0,0 +1,38 @@
package validation
import (
"strconv"
"github.com/go-playground/validator/v10"
)
func ValidateDriversLicence(fl validator.FieldLevel) bool {
fieldValue := fl.Field().String()
if len(fieldValue) != 11 {
return false
}
id, tenthChar := string(fieldValue[:9]), string(fieldValue[9])
if tenthChar == "X" {
tenthChar = "10"
}
tenthValue, _ := strconv.ParseInt(tenthChar, 10, 8)
// for readability
weights := []int{9, 8, 7, 6, 5, 4, 3, 2, 1}
sum := 0
for i := 0; i < 9; i++ {
char := string(id[i])
value, _ := strconv.ParseInt(char, 36, 64)
sum += int(value) * weights[i]
}
calcCheckDigit := sum % 11
if calcCheckDigit != int(tenthValue) {
return false
}
return true
}

View File

@@ -0,0 +1,19 @@
package validation
import (
"github.com/go-playground/validator/v10"
"github.com/jbub/banking/iban"
"github.com/jbub/banking/swift"
)
func IBANValidator(fl validator.FieldLevel) bool {
fieldValue := fl.Field().String()
return iban.Validate(fieldValue) == nil
}
func BICValidator(fl validator.FieldLevel) bool {
fieldValue := fl.Field().String()
return swift.Validate(fieldValue) == nil
}

View File

@@ -0,0 +1,34 @@
package validation
import (
"regexp"
"strings"
"github.com/go-playground/validator/v10"
)
var xssPatterns = []*regexp.Regexp{
regexp.MustCompile(`(?i)<script`),
regexp.MustCompile(`(?i)javascript:`),
regexp.MustCompile(`(?i)on\w+\s*=`),
regexp.MustCompile(`(?i)(vbscript|data):`),
regexp.MustCompile(`(?i)<(iframe|object|embed|applet)`),
regexp.MustCompile(`(?i)expression\s*\(`),
regexp.MustCompile(`(?i)url\s*\(`),
regexp.MustCompile(`(?i)<\?`),
regexp.MustCompile(`(?i)<%`),
regexp.MustCompile(`(?i)<!\[CDATA\[`),
regexp.MustCompile(`(?i)<(svg|animate)`),
regexp.MustCompile(`(?i)<(audio|video|source)`),
regexp.MustCompile(`(?i)base64`),
}
func ValidateSafeContent(fl validator.FieldLevel) bool {
input := strings.ToLower(fl.Field().String())
for _, pattern := range xssPatterns {
if pattern.MatchString(input) {
return false
}
}
return true
}

View File

@@ -0,0 +1,30 @@
package validation
import (
"GoMembership/internal/models"
"GoMembership/internal/repositories"
"github.com/go-playground/validator/v10"
)
func validateMembership(sl validator.StructLevel, membership models.Membership) {
if membership.SubscriptionModel.RequiredMembershipField != "" {
switch membership.SubscriptionModel.RequiredMembershipField {
case "ParentMembershipID":
if membership.ParentMembershipID == 0 {
sl.ReportError(membership.ParentMembershipID, membership.SubscriptionModel.RequiredMembershipField,
"RequiredMembershipField", "required", "")
} else {
_, err := repositories.GetUserByID(&membership.ParentMembershipID)
if err != nil {
sl.ReportError(membership.ParentMembershipID, membership.SubscriptionModel.RequiredMembershipField,
"RequiredMembershipField", "user_id_not_found", "")
}
}
default:
sl.ReportError(membership.ParentMembershipID, membership.SubscriptionModel.RequiredMembershipField,
"RequiredMembershipField", "not_implemented", "")
}
}
}

View File

@@ -0,0 +1,23 @@
package validation
import (
"GoMembership/internal/models"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
)
func SetupValidators() {
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
// Register custom validators
v.RegisterValidation("safe_content", ValidateSafeContent)
v.RegisterValidation("iban", IBANValidator)
v.RegisterValidation("bic", BICValidator)
v.RegisterValidation("euDriversLicence", ValidateDriversLicence)
// Register struct-level validations
v.RegisterStructValidation(validateUser, models.User{})
v.RegisterStructValidation(ValidateSubscription, models.SubscriptionModel{})
}
}

View File

@@ -0,0 +1,46 @@
package validation
import (
"GoMembership/internal/models"
"GoMembership/internal/repositories"
"github.com/go-playground/validator/v10"
)
// ValidateNewSubscription validates a new subscription model being created
func ValidateSubscription(sl validator.StructLevel) {
subscription := sl.Current().Interface().(models.SubscriptionModel)
if subscription.Name == "" {
sl.ReportError(subscription.Name, "Name", "name", "required", "")
}
if sl.Parent().Type().Name() == "MembershipData" {
// This is subscription only operation
if subscription.Details == "" {
sl.ReportError(subscription.Details, "Details", "details", "required", "")
}
if subscription.MonthlyFee < 0 {
sl.ReportError(subscription.MonthlyFee, "MonthlyFee", "monthly_fee", "gte", "0")
}
if subscription.HourlyRate < 0 {
sl.ReportError(subscription.HourlyRate, "HourlyRate", "hourly_rate", "gte", "0")
}
if subscription.IncludedPerYear < 0 {
sl.ReportError(subscription.IncludedPerYear, "IncludedPerYear", "included_hours_per_year", "gte", "0")
}
if subscription.IncludedPerMonth < 0 {
sl.ReportError(subscription.IncludedPerMonth, "IncludedPerMonth", "included_hours_per_month", "gte", "0")
}
} else {
// This is a nested probably user struct. We are only checking if the model exists
existingSubscription, err := repositories.GetModelByName(&subscription.Name)
if err != nil || existingSubscription == nil {
sl.ReportError(subscription.Name, "Name", "name", "exists", "")
}
}
}

View File

@@ -0,0 +1,51 @@
package validation
import (
"GoMembership/internal/models"
"GoMembership/internal/repositories"
"GoMembership/pkg/logger"
"time"
"github.com/go-playground/validator/v10"
)
func validateUser(sl validator.StructLevel) {
user := sl.Current().Interface().(models.User)
if user.DateOfBirth.After(time.Now().AddDate(-18, 0, 0)) {
sl.ReportError(user.DateOfBirth, "DateOfBirth", "date_of_birth", "age", "")
}
if user.Membership.SubscriptionModel.Name == "" {
sl.ReportError(user.Membership.SubscriptionModel.Name, "SubscriptionModel.Name", "name", "required", "")
} else {
selectedModel, err := repositories.GetModelByName(&user.Membership.SubscriptionModel.Name)
if err != nil {
logger.Error.Printf("Error finding subscription model for user %v: %v", user.Email, err)
sl.ReportError(user.Membership.SubscriptionModel.Name, "SubscriptionModel.Name", "name", "invalid", "")
} else {
user.Membership.SubscriptionModel = *selectedModel
}
}
validateMembership(sl, user.Membership)
}
// func RequiredIfNotAdmin(fl validator.FieldLevel) bool {
// // Traverse up the struct hierarchy to find the IsAdmin field
// current := fl.Parent()
// // Check multiple levels of nesting to find userRole
// for current.IsValid() {
// if isRoleIDField := current.FieldByName("RoleID"); isRoleIDField.IsValid() {
// // If IsAdmin is found and is true, skip validation
// if isRoleIDField.Interface().(int8) == constants.Roles.Admin{
// return true
// }
// break
// }
// current = current.Parent() // Move to the next parent level
// }
// If not an admin, enforce that the field must have a non-zero value
// return !fl.Field().IsZero()
// }