94d0fbef38
- Introduced a new tender approval management system, including the creation of tender approval entities, services, and repositories. - Implemented CRUD operations for tender approvals, allowing companies to approve or reject tenders. - Developed administrative and public API endpoints for listing, retrieving, and updating tender approvals with comprehensive filtering options. - Enhanced Swagger documentation to accurately reflect the new endpoints, including detailed descriptions, parameters, and response formats. - Updated existing routes to include tender approval management, ensuring adherence to Clean Architecture principles and maintaining a clear separation of concerns in the handler layer.
177 lines
4.1 KiB
Go
177 lines
4.1 KiB
Go
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)<script[^>]*>.*?</script>`)
|
|
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
|
|
}
|