package tender_approval import ( "regexp" "strings" ) // Validation functions for tender approval domain // IsValidTenderID validates if the tender ID format is correct func IsValidTenderID(tenderID string) bool { if tenderID == "" { return false } // Tender ID should be a non-empty string // You can add more specific validation rules here based on your tender ID format return len(tenderID) > 0 && len(tenderID) <= 100 } // IsValidCompanyID validates if the company ID format is correct func IsValidCompanyID(companyID string) bool { if companyID == "" { return false } // Company ID should be a non-empty string // You can add more specific validation rules here based on your company ID format return len(companyID) > 0 && len(companyID) <= 100 } // IsValidSubmissionMode validates if the submission mode is valid func IsValidSubmissionMode(mode string) bool { validModes := []string{ string(SubmissionModeSelfApply), string(SubmissionModePartnership), } for _, validMode := range validModes { if strings.EqualFold(mode, validMode) { return true } } return false } // IsValidStatus validates if the approval status is valid func IsValidStatus(status string) bool { validStatuses := []string{ string(ApprovalStatusApproved), string(ApprovalStatusRejected), } for _, validStatus := range validStatuses { if strings.EqualFold(status, validStatus) { return true } } return false } // IsValidNotes validates if the notes field is valid func IsValidNotes(notes *string) bool { if notes == nil { return true // Notes are optional } // Notes should be between 0 and 1000 characters return len(*notes) <= 1000 } // IsValidReason validates if the rejection reason is valid func IsValidReason(reason string) bool { // Reason should be between 10 and 500 characters if len(reason) < 10 || len(reason) > 500 { return false } // Reason should not contain only whitespace if strings.TrimSpace(reason) == "" { return false } return true } // IsValidTimestamp validates if the timestamp is within reasonable range func IsValidTimestamp(timestamp int64) bool { // Timestamp should be positive and not too far in the future // You can adjust these limits based on your requirements if timestamp <= 0 { return false } // Check if timestamp is not too far in the future (e.g., 10 years from now) maxFutureTimestamp := int64(10 * 365 * 24 * 60 * 60) // 10 years in seconds return timestamp <= maxFutureTimestamp } // IsValidLimit validates if the limit parameter is valid func IsValidLimit(limit int) bool { return limit > 0 && limit <= 100 } // IsValidOffset validates if the offset parameter is valid func IsValidOffset(offset int) bool { return offset >= 0 } // IsValidSortBy validates if the sort by parameter is valid func IsValidSortBy(sortBy string) bool { validSortFields := []string{ "created_at", "updated_at", "status", "submission_mode", } for _, validField := range validSortFields { if strings.EqualFold(sortBy, validField) { return true } } return false } // IsValidSortOrder validates if the sort order parameter is valid func IsValidSortOrder(sortOrder string) bool { validOrders := []string{"asc", "desc"} for _, validOrder := range validOrders { if strings.EqualFold(sortOrder, validOrder) { return true } } return false } // SanitizeString removes potentially dangerous characters from input strings func SanitizeString(input string) string { // Remove HTML tags htmlTagRegex := regexp.MustCompile(`<[^>]*>`) sanitized := htmlTagRegex.ReplaceAllString(input, "") // Remove script tags scriptRegex := regexp.MustCompile(`(?i)]*>.*?`) sanitized = scriptRegex.ReplaceAllString(sanitized, "") // Trim whitespace sanitized = strings.TrimSpace(sanitized) return sanitized } // ValidateSearchQuery validates if the search query is valid func ValidateSearchQuery(query string) bool { if query == "" { return true // Empty query is valid } // Query should not be too long if len(query) > 200 { return false } // Query should not contain only special characters if regexp.MustCompile(`^[^a-zA-Z0-9\s]+$`).MatchString(query) { return false } return true }