xss validation
This commit is contained in:
@@ -2,8 +2,11 @@ package inquiry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"tm/pkg/security"
|
||||
)
|
||||
|
||||
// EmailTemplateData represents the data needed for the email template
|
||||
@@ -20,7 +23,14 @@ type EmailTemplateData struct {
|
||||
}
|
||||
|
||||
// GenerateNewInquiryEmailTemplate generates a beautiful HTML email template for new inquiry notifications
|
||||
func GenerateNewInquiryEmailTemplate(data *EmailTemplateData) string {
|
||||
func GenerateNewInquiryEmailTemplate(data *EmailTemplateData, xssPolicy *security.XSSPolicy) string {
|
||||
// Sanitize all user inputs before inserting into HTML
|
||||
safeFullName := html.EscapeString(data.FullName)
|
||||
safeCompanyName := html.EscapeString(data.CompanyName)
|
||||
safeWorkEmail := html.EscapeString(data.WorkEmail)
|
||||
safePhoneNumber := html.EscapeString(data.PhoneNumber)
|
||||
safeInquiryID := html.EscapeString(data.InquiryID)
|
||||
|
||||
// Format the creation date
|
||||
createdAt := time.Unix(data.CreatedAt, 0).Format("January 2, 2006 at 3:04 PM")
|
||||
|
||||
@@ -249,12 +259,12 @@ func GenerateNewInquiryEmailTemplate(data *EmailTemplateData) string {
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
// Replace placeholders with actual data
|
||||
html = strings.ReplaceAll(html, "{{COMPANY_NAME}}", data.CompanyName)
|
||||
html = strings.ReplaceAll(html, "{{INQUIRY_ID}}", data.InquiryID)
|
||||
html = strings.ReplaceAll(html, "{{FULL_NAME}}", data.FullName)
|
||||
html = strings.ReplaceAll(html, "{{WORK_EMAIL}}", data.WorkEmail)
|
||||
html = strings.ReplaceAll(html, "{{PHONE_NUMBER}}", data.PhoneNumber)
|
||||
// Replace placeholders with sanitized data
|
||||
html = strings.ReplaceAll(html, "{{COMPANY_NAME}}", safeCompanyName)
|
||||
html = strings.ReplaceAll(html, "{{INQUIRY_ID}}", safeInquiryID)
|
||||
html = strings.ReplaceAll(html, "{{FULL_NAME}}", safeFullName)
|
||||
html = strings.ReplaceAll(html, "{{WORK_EMAIL}}", safeWorkEmail)
|
||||
html = strings.ReplaceAll(html, "{{PHONE_NUMBER}}", safePhoneNumber)
|
||||
html = strings.ReplaceAll(html, "{{CREATED_AT}}", createdAt)
|
||||
|
||||
return html
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package inquiry
|
||||
|
||||
import "tm/pkg/response"
|
||||
import (
|
||||
"tm/pkg/response"
|
||||
"tm/pkg/security"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
)
|
||||
|
||||
// Inquiry DTOs
|
||||
|
||||
@@ -83,3 +88,72 @@ func (i *Inquiry) ToResponse() *InquiryResponse {
|
||||
UpdatedAt: i.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateAndSanitize validates and sanitizes the form
|
||||
func (f *CreateInquiryForm) ValidateAndSanitize(xssPolicy *security.XSSPolicy) error {
|
||||
var err error
|
||||
|
||||
// Sanitize and validate FullName
|
||||
f.FullName, err = xssPolicy.ValidateAndSanitizeInput(f.FullName, "text")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sanitize and validate CompanyName
|
||||
f.CompanyName, err = xssPolicy.ValidateAndSanitizeInput(f.CompanyName, "text")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sanitize and validate WorkEmail (email validation is separate)
|
||||
f.WorkEmail, err = xssPolicy.ValidateAndSanitizeInput(f.WorkEmail, "email")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sanitize and validate PhoneNumber
|
||||
f.PhoneNumber, err = xssPolicy.ValidateAndSanitizeInput(f.PhoneNumber, "phone")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Standard govalidator validation
|
||||
_, err = govalidator.ValidateStruct(f)
|
||||
return err
|
||||
}
|
||||
|
||||
// ValidateAndSanitize validates and sanitizes the status update form
|
||||
func (f *UpdateInquiryStatusForm) ValidateAndSanitize(xssPolicy *security.XSSPolicy) error {
|
||||
var err error
|
||||
|
||||
// Sanitize Reason
|
||||
f.Reason, err = xssPolicy.ValidateAndSanitizeInput(f.Reason, "text")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sanitize Description
|
||||
f.Description, err = xssPolicy.ValidateAndSanitizeInput(f.Description, "html")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Standard govalidator validation
|
||||
_, err = govalidator.ValidateStruct(f)
|
||||
return err
|
||||
}
|
||||
|
||||
// ValidateAndSanitize validates and sanitizes the search form
|
||||
func (f *SearchInquiriesForm) ValidateAndSanitize(xssPolicy *security.XSSPolicy) error {
|
||||
if f.Search != nil {
|
||||
sanitized, err := xssPolicy.ValidateAndSanitizeInput(*f.Search, "text")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*f.Search = sanitized
|
||||
}
|
||||
|
||||
// Standard govalidator validation
|
||||
_, err := govalidator.ValidateStruct(f)
|
||||
return err
|
||||
}
|
||||
|
||||
+14
-12
@@ -4,22 +4,24 @@ import (
|
||||
"encoding/json"
|
||||
"tm/pkg/logger"
|
||||
"tm/pkg/response"
|
||||
"tm/pkg/security"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// Handler handles HTTP requests for inquiry operations
|
||||
type Handler struct {
|
||||
service Service
|
||||
logger logger.Logger
|
||||
service Service
|
||||
logger logger.Logger
|
||||
xssPolicy *security.XSSPolicy
|
||||
}
|
||||
|
||||
// NewInquiryHandler creates a new inquiry handler
|
||||
func NewHandler(service Service, logger logger.Logger) *Handler {
|
||||
func NewHandler(service Service, logger logger.Logger, xssPolicy *security.XSSPolicy) *Handler {
|
||||
return &Handler{
|
||||
service: service,
|
||||
logger: logger,
|
||||
service: service,
|
||||
logger: logger,
|
||||
xssPolicy: xssPolicy,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,8 +44,8 @@ func (h *Handler) CreateInquiry(c echo.Context) error {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
// Validate form
|
||||
if _, err := govalidator.ValidateStruct(form); err != nil {
|
||||
// Validate and sanitize form
|
||||
if err := form.ValidateAndSanitize(h.xssPolicy); err != nil {
|
||||
return response.ValidationError(c, err.Error(), "")
|
||||
}
|
||||
|
||||
@@ -122,8 +124,8 @@ func (h *Handler) UpdateInquiryStatus(c echo.Context) error {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
// Validate form
|
||||
if _, err := govalidator.ValidateStruct(form); err != nil {
|
||||
// Validate and sanitize form
|
||||
if err := form.ValidateAndSanitize(h.xssPolicy); err != nil {
|
||||
return response.ValidationError(c, err.Error(), "")
|
||||
}
|
||||
|
||||
@@ -163,8 +165,8 @@ func (h *Handler) SearchInquiries(c echo.Context) error {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
// Validate form
|
||||
if _, err := govalidator.ValidateStruct(form); err != nil {
|
||||
// Validate and sanitize form
|
||||
if err := form.ValidateAndSanitize(h.xssPolicy); err != nil {
|
||||
return response.ValidationError(c, err.Error(), "")
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"tm/pkg/logger"
|
||||
"tm/pkg/notification"
|
||||
"tm/pkg/response"
|
||||
"tm/pkg/security"
|
||||
)
|
||||
|
||||
// Service defines business logic for inquiry operations
|
||||
@@ -23,14 +24,16 @@ type inquiryService struct {
|
||||
repository Repository
|
||||
sdk notification.SDK
|
||||
logger logger.Logger
|
||||
xssPolicy *security.XSSPolicy
|
||||
}
|
||||
|
||||
// NewService creates a new inquiry service
|
||||
func NewService(repository Repository, sdk notification.SDK, logger logger.Logger) Service {
|
||||
func NewService(repository Repository, sdk notification.SDK, logger logger.Logger, xssPolicy *security.XSSPolicy) Service {
|
||||
return &inquiryService{
|
||||
repository: repository,
|
||||
sdk: sdk,
|
||||
logger: logger,
|
||||
xssPolicy: xssPolicy,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +117,7 @@ func (s *inquiryService) Create(ctx context.Context, form *CreateInquiryForm) (*
|
||||
CompanyLogo: "",
|
||||
CompanyURL: "https://opplens.com",
|
||||
SupportEmail: "info@opplens.com",
|
||||
}),
|
||||
}, s.xssPolicy),
|
||||
Type: "alert",
|
||||
Priority: "important",
|
||||
EventType: notification.EventTypeEmail,
|
||||
@@ -137,7 +140,7 @@ func (s *inquiryService) Create(ctx context.Context, form *CreateInquiryForm) (*
|
||||
CompanyLogo: "",
|
||||
CompanyURL: "https://opplens.com",
|
||||
SupportEmail: "info@opplens.com",
|
||||
}),
|
||||
}, s.xssPolicy),
|
||||
Type: "alert",
|
||||
Priority: "important",
|
||||
EventType: notification.EventTypeEmail,
|
||||
|
||||
Reference in New Issue
Block a user