Add Campaign
This commit is contained in:
@@ -0,0 +1,336 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"apskel-pos-be/internal/constants"
|
||||
"apskel-pos-be/internal/contract"
|
||||
)
|
||||
|
||||
type CampaignValidator interface {
|
||||
ValidateCreateCampaignRequest(req *contract.CreateCampaignRequest) (error, string)
|
||||
ValidateUpdateCampaignRequest(req *contract.UpdateCampaignRequest) (error, string)
|
||||
ValidateListCampaignsRequest(req *contract.ListCampaignsRequest) (error, string)
|
||||
ValidateGetCampaignRequest(req *contract.GetCampaignRequest) (error, string)
|
||||
ValidateDeleteCampaignRequest(req *contract.DeleteCampaignRequest) (error, string)
|
||||
ValidateCreateCampaignRuleRequest(req *contract.CreateCampaignRuleRequest) (error, string)
|
||||
ValidateUpdateCampaignRuleRequest(req *contract.UpdateCampaignRuleRequest) (error, string)
|
||||
ValidateListCampaignRulesRequest(req *contract.ListCampaignRulesRequest) (error, string)
|
||||
ValidateGetCampaignRuleRequest(req *contract.GetCampaignRuleRequest) (error, string)
|
||||
ValidateDeleteCampaignRuleRequest(req *contract.DeleteCampaignRuleRequest) (error, string)
|
||||
}
|
||||
|
||||
type CampaignValidatorImpl struct{}
|
||||
|
||||
func NewCampaignValidator() CampaignValidator {
|
||||
return &CampaignValidatorImpl{}
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) ValidateCreateCampaignRequest(req *contract.CreateCampaignRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate name
|
||||
if strings.TrimSpace(req.Name) == "" {
|
||||
return errors.New("campaign name is required"), constants.ValidationErrorCode
|
||||
}
|
||||
if len(req.Name) > 150 {
|
||||
return errors.New("campaign name cannot exceed 150 characters"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate campaign type
|
||||
if !v.isValidCampaignType(req.Type) {
|
||||
return errors.New("invalid campaign type. Valid types are: REWARD, POINTS, TOKENS, MIXED"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate date range
|
||||
if err := v.validateDateRange(req.StartDate, req.EndDate); err != nil {
|
||||
return err, constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate position
|
||||
if req.Position < 0 {
|
||||
return errors.New("position cannot be negative"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate rules
|
||||
if len(req.Rules) == 0 {
|
||||
return errors.New("at least one rule is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
for i, rule := range req.Rules {
|
||||
if err := v.validateCampaignRule(&rule, i+1); err != nil {
|
||||
return err, constants.ValidationErrorCode
|
||||
}
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) ValidateUpdateCampaignRequest(req *contract.UpdateCampaignRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate ID
|
||||
if req.ID.String() == "" {
|
||||
return errors.New("campaign ID is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate name
|
||||
if strings.TrimSpace(req.Name) == "" {
|
||||
return errors.New("campaign name is required"), constants.ValidationErrorCode
|
||||
}
|
||||
if len(req.Name) > 150 {
|
||||
return errors.New("campaign name cannot exceed 150 characters"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate campaign type
|
||||
if !v.isValidCampaignType(req.Type) {
|
||||
return errors.New("invalid campaign type. Valid types are: REWARD, POINTS, TOKENS, MIXED"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate date range
|
||||
if err := v.validateDateRange(req.StartDate, req.EndDate); err != nil {
|
||||
return err, constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate position
|
||||
if req.Position < 0 {
|
||||
return errors.New("position cannot be negative"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate rules
|
||||
if len(req.Rules) == 0 {
|
||||
return errors.New("at least one rule is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
for i, rule := range req.Rules {
|
||||
if err := v.validateCampaignRule(&rule, i+1); err != nil {
|
||||
return err, constants.ValidationErrorCode
|
||||
}
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) ValidateListCampaignsRequest(req *contract.ListCampaignsRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate pagination
|
||||
if req.Page < 1 {
|
||||
return errors.New("page must be greater than 0"), constants.ValidationErrorCode
|
||||
}
|
||||
if req.Limit < 1 {
|
||||
return errors.New("limit must be greater than 0"), constants.ValidationErrorCode
|
||||
}
|
||||
if req.Limit > 100 {
|
||||
return errors.New("limit cannot exceed 100"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate campaign type filter if provided
|
||||
if req.Type != "" && !v.isValidCampaignType(req.Type) {
|
||||
return errors.New("invalid campaign type filter. Valid types are: REWARD, POINTS, TOKENS, MIXED"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) ValidateGetCampaignRequest(req *contract.GetCampaignRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
if req.ID.String() == "" {
|
||||
return errors.New("campaign ID is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) ValidateDeleteCampaignRequest(req *contract.DeleteCampaignRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
if req.ID.String() == "" {
|
||||
return errors.New("campaign ID is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) ValidateCreateCampaignRuleRequest(req *contract.CreateCampaignRuleRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate campaign ID
|
||||
if req.CampaignID.String() == "" {
|
||||
return errors.New("campaign ID is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate rule
|
||||
if err := v.validateCampaignRule(&contract.CampaignRuleStruct{
|
||||
RuleType: req.RuleType,
|
||||
ConditionValue: req.ConditionValue,
|
||||
RewardType: req.RewardType,
|
||||
RewardValue: req.RewardValue,
|
||||
RewardSubtype: req.RewardSubtype,
|
||||
RewardRefID: req.RewardRefID,
|
||||
Metadata: req.Metadata,
|
||||
}, 1); err != nil {
|
||||
return err, constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) ValidateUpdateCampaignRuleRequest(req *contract.UpdateCampaignRuleRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate ID
|
||||
if req.ID.String() == "" {
|
||||
return errors.New("campaign rule ID is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate campaign ID
|
||||
if req.CampaignID.String() == "" {
|
||||
return errors.New("campaign ID is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate rule
|
||||
if err := v.validateCampaignRule(&contract.CampaignRuleStruct{
|
||||
RuleType: req.RuleType,
|
||||
ConditionValue: req.ConditionValue,
|
||||
RewardType: req.RewardType,
|
||||
RewardValue: req.RewardValue,
|
||||
RewardSubtype: req.RewardSubtype,
|
||||
RewardRefID: req.RewardRefID,
|
||||
Metadata: req.Metadata,
|
||||
}, 1); err != nil {
|
||||
return err, constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) ValidateListCampaignRulesRequest(req *contract.ListCampaignRulesRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate pagination
|
||||
if req.Page < 1 {
|
||||
return errors.New("page must be greater than 0"), constants.ValidationErrorCode
|
||||
}
|
||||
if req.Limit < 1 {
|
||||
return errors.New("limit must be greater than 0"), constants.ValidationErrorCode
|
||||
}
|
||||
if req.Limit > 100 {
|
||||
return errors.New("limit cannot exceed 100"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate rule type filter if provided
|
||||
if req.RuleType != "" && !v.isValidRuleType(req.RuleType) {
|
||||
return errors.New("invalid rule type filter. Valid types are: TIER, SPEND, PRODUCT, CATEGORY, DAY, LOCATION"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate reward type filter if provided
|
||||
if req.RewardType != "" && !v.isValidRewardType(req.RewardType) {
|
||||
return errors.New("invalid reward type filter. Valid types are: POINTS, TOKENS, REWARD"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) ValidateGetCampaignRuleRequest(req *contract.GetCampaignRuleRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
if req.ID.String() == "" {
|
||||
return errors.New("campaign rule ID is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) ValidateDeleteCampaignRuleRequest(req *contract.DeleteCampaignRuleRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
if req.ID.String() == "" {
|
||||
return errors.New("campaign rule ID is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) isValidCampaignType(campaignType string) bool {
|
||||
validTypes := []string{"REWARD", "POINTS", "TOKENS", "MIXED"}
|
||||
return contains(validTypes, campaignType)
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) isValidRuleType(ruleType string) bool {
|
||||
validTypes := []string{"TIER", "SPEND", "PRODUCT", "CATEGORY", "DAY", "LOCATION"}
|
||||
return contains(validTypes, ruleType)
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) isValidRewardType(rewardType string) bool {
|
||||
validTypes := []string{"POINTS", "TOKENS", "REWARD"}
|
||||
return contains(validTypes, rewardType)
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) validateDateRange(startDate, endDate time.Time) error {
|
||||
if startDate.IsZero() {
|
||||
return errors.New("start date is required")
|
||||
}
|
||||
if endDate.IsZero() {
|
||||
return errors.New("end date is required")
|
||||
}
|
||||
if startDate.After(endDate) {
|
||||
return errors.New("start date cannot be after end date")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *CampaignValidatorImpl) validateCampaignRule(rule *contract.CampaignRuleStruct, ruleNumber int) error {
|
||||
if rule == nil {
|
||||
return errors.New("rule is required")
|
||||
}
|
||||
|
||||
// Validate rule type
|
||||
if !v.isValidRuleType(rule.RuleType) {
|
||||
return errors.New("invalid rule type in rule " + string(rune(ruleNumber)) + ". Valid types are: TIER, SPEND, PRODUCT, CATEGORY, DAY, LOCATION")
|
||||
}
|
||||
|
||||
// Validate reward type
|
||||
if !v.isValidRewardType(rule.RewardType) {
|
||||
return errors.New("invalid reward type in rule " + string(rune(ruleNumber)) + ". Valid types are: POINTS, TOKENS, REWARD")
|
||||
}
|
||||
|
||||
// Validate reward value based on reward type
|
||||
if rule.RewardType == "POINTS" || rule.RewardType == "TOKENS" {
|
||||
if rule.RewardValue == nil || *rule.RewardValue <= 0 {
|
||||
return errors.New("reward value must be positive for " + rule.RewardType + " type in rule " + string(rune(ruleNumber)))
|
||||
}
|
||||
}
|
||||
|
||||
// Validate reward reference ID for REWARD type
|
||||
if rule.RewardType == "REWARD" {
|
||||
if rule.RewardRefID == nil {
|
||||
return errors.New("reward reference ID is required for REWARD type in rule " + string(rune(ruleNumber)))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"apskel-pos-be/internal/constants"
|
||||
"apskel-pos-be/internal/contract"
|
||||
)
|
||||
|
||||
type RewardValidator interface {
|
||||
ValidateCreateRewardRequest(req *contract.CreateRewardRequest) (error, string)
|
||||
ValidateUpdateRewardRequest(req *contract.UpdateRewardRequest) (error, string)
|
||||
ValidateListRewardsRequest(req *contract.ListRewardsRequest) (error, string)
|
||||
ValidateGetRewardRequest(req *contract.GetRewardRequest) (error, string)
|
||||
ValidateDeleteRewardRequest(req *contract.DeleteRewardRequest) (error, string)
|
||||
}
|
||||
|
||||
type RewardValidatorImpl struct{}
|
||||
|
||||
func NewRewardValidator() RewardValidator {
|
||||
return &RewardValidatorImpl{}
|
||||
}
|
||||
|
||||
func (v *RewardValidatorImpl) ValidateCreateRewardRequest(req *contract.CreateRewardRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate name
|
||||
if strings.TrimSpace(req.Name) == "" {
|
||||
return errors.New("reward name is required"), constants.ValidationErrorCode
|
||||
}
|
||||
if len(req.Name) > 150 {
|
||||
return errors.New("reward name cannot exceed 150 characters"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate reward type
|
||||
if !v.isValidRewardType(req.RewardType) {
|
||||
return errors.New("invalid reward type. Valid types are: VOUCHER, PHYSICAL, DIGITAL, BALANCE"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate cost points
|
||||
if req.CostPoints <= 0 {
|
||||
return errors.New("cost points must be greater than 0"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate stock
|
||||
if req.Stock != nil && *req.Stock < 0 {
|
||||
return errors.New("stock cannot be negative"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate max per customer
|
||||
if req.MaxPerCustomer <= 0 {
|
||||
return errors.New("max per customer must be greater than 0"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate TNC if provided
|
||||
if req.Tnc != nil {
|
||||
if err := v.validateTermsAndConditions(req.Tnc); err != nil {
|
||||
return err, constants.ValidationErrorCode
|
||||
}
|
||||
}
|
||||
|
||||
// Validate images if provided
|
||||
if req.Images != nil {
|
||||
if err := v.validateImages(*req.Images); err != nil {
|
||||
return err, constants.ValidationErrorCode
|
||||
}
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *RewardValidatorImpl) ValidateUpdateRewardRequest(req *contract.UpdateRewardRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate ID
|
||||
if req.ID.String() == "" {
|
||||
return errors.New("reward ID is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate name
|
||||
if strings.TrimSpace(req.Name) == "" {
|
||||
return errors.New("reward name is required"), constants.ValidationErrorCode
|
||||
}
|
||||
if len(req.Name) > 150 {
|
||||
return errors.New("reward name cannot exceed 150 characters"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate reward type
|
||||
if !v.isValidRewardType(req.RewardType) {
|
||||
return errors.New("invalid reward type. Valid types are: VOUCHER, PHYSICAL, DIGITAL, BALANCE"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate cost points
|
||||
if req.CostPoints <= 0 {
|
||||
return errors.New("cost points must be greater than 0"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate stock
|
||||
if req.Stock != nil && *req.Stock < 0 {
|
||||
return errors.New("stock cannot be negative"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate max per customer
|
||||
if req.MaxPerCustomer <= 0 {
|
||||
return errors.New("max per customer must be greater than 0"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate TNC if provided
|
||||
if req.Tnc != nil {
|
||||
if err := v.validateTermsAndConditions(req.Tnc); err != nil {
|
||||
return err, constants.ValidationErrorCode
|
||||
}
|
||||
}
|
||||
|
||||
// Validate images if provided
|
||||
if req.Images != nil {
|
||||
if err := v.validateImages(*req.Images); err != nil {
|
||||
return err, constants.ValidationErrorCode
|
||||
}
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *RewardValidatorImpl) ValidateListRewardsRequest(req *contract.ListRewardsRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate pagination
|
||||
if req.Page < 1 {
|
||||
return errors.New("page must be greater than 0"), constants.ValidationErrorCode
|
||||
}
|
||||
if req.Limit < 1 {
|
||||
return errors.New("limit must be greater than 0"), constants.ValidationErrorCode
|
||||
}
|
||||
if req.Limit > 100 {
|
||||
return errors.New("limit cannot exceed 100"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate reward type filter if provided
|
||||
if req.RewardType != "" && !v.isValidRewardType(req.RewardType) {
|
||||
return errors.New("invalid reward type filter. Valid types are: VOUCHER, PHYSICAL, DIGITAL, BALANCE"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
// Validate points range if provided
|
||||
if req.MinPoints != nil && req.MaxPoints != nil {
|
||||
if *req.MinPoints > *req.MaxPoints {
|
||||
return errors.New("min points cannot be greater than max points"), constants.ValidationErrorCode
|
||||
}
|
||||
if *req.MinPoints < 0 {
|
||||
return errors.New("min points cannot be negative"), constants.ValidationErrorCode
|
||||
}
|
||||
if *req.MaxPoints < 0 {
|
||||
return errors.New("max points cannot be negative"), constants.ValidationErrorCode
|
||||
}
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *RewardValidatorImpl) ValidateGetRewardRequest(req *contract.GetRewardRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
if req.ID.String() == "" {
|
||||
return errors.New("reward ID is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *RewardValidatorImpl) ValidateDeleteRewardRequest(req *contract.DeleteRewardRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
if req.ID.String() == "" {
|
||||
return errors.New("reward ID is required"), constants.ValidationErrorCode
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *RewardValidatorImpl) isValidRewardType(rewardType string) bool {
|
||||
validTypes := []string{"VOUCHER", "PHYSICAL", "DIGITAL", "BALANCE"}
|
||||
return contains(validTypes, rewardType)
|
||||
}
|
||||
|
||||
func (v *RewardValidatorImpl) validateTermsAndConditions(tnc *contract.TermsAndConditionsStruct) error {
|
||||
if tnc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate expiry days
|
||||
if tnc.ExpiryDays < 0 {
|
||||
return errors.New("expiry days cannot be negative")
|
||||
}
|
||||
|
||||
// Validate sections
|
||||
if len(tnc.Sections) == 0 {
|
||||
return errors.New("terms and conditions must have at least one section")
|
||||
}
|
||||
|
||||
for i, section := range tnc.Sections {
|
||||
if strings.TrimSpace(section.Title) == "" {
|
||||
return errors.New("section title is required")
|
||||
}
|
||||
if len(section.Rules) == 0 {
|
||||
return errors.New("section must have at least one rule")
|
||||
}
|
||||
for j, rule := range section.Rules {
|
||||
if strings.TrimSpace(rule) == "" {
|
||||
return errors.New("rule cannot be empty")
|
||||
}
|
||||
if len(rule) > 500 {
|
||||
return errors.New("rule cannot exceed 500 characters")
|
||||
}
|
||||
// Validate rule content (basic validation)
|
||||
if len(rule) < 10 {
|
||||
return errors.New("rule must be at least 10 characters long")
|
||||
}
|
||||
_ = j // Avoid unused variable warning
|
||||
}
|
||||
_ = i // Avoid unused variable warning
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *RewardValidatorImpl) validateImages(images []string) error {
|
||||
if len(images) == 0 {
|
||||
return errors.New("at least one image is required")
|
||||
}
|
||||
|
||||
for i, imgURL := range images {
|
||||
if strings.TrimSpace(imgURL) == "" {
|
||||
return errors.New("image URL is required")
|
||||
}
|
||||
|
||||
// Validate URL format (basic validation)
|
||||
if !v.isValidURL(imgURL) {
|
||||
return errors.New("invalid image URL format")
|
||||
}
|
||||
|
||||
_ = i // Avoid unused variable warning
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *RewardValidatorImpl) isValidURL(url string) bool {
|
||||
// Basic URL validation regex
|
||||
urlRegex := regexp.MustCompile(`^https?://[^\s/$.?#].[^\s]*$`)
|
||||
return urlRegex.MatchString(url)
|
||||
}
|
||||
Reference in New Issue
Block a user