- Add comprehensive API-key authentication system with X-API-Key header validation - Implement permission-based access control (mail:send, * for admin) - Add rate-limiting system (60 req/hour per API key, 100 req/hour per IP) - Refactor monolithic 590-line main.lua into 6 modular components (<200 lines each) - Add IP-restriction support with CIDR notation (127.0.0.1, 10.0.0.0/8) - Implement Hugo integration with CORS support for localhost:1313 - Add production-ready configuration with environment variable support - Create comprehensive testing suite (auth, rate-limiting, stress tests) - Add production deployment checklist and cleanup scripts This refactoring transforms the API gateway from a single-file monolith into a biocodie-compliant modular architecture while adding enterprise-grade security features. Performance testing shows 79 RPS concurrent throughput with <100ms latency. Hugo contact form integration tested and working. System is now production-ready for deployment to walter/aitvaras. Resolves #47
113 lines
3.4 KiB
Lua
113 lines
3.4 KiB
Lua
-- furt-lua/src/routes/mail.lua
|
|
-- Mail service route handler
|
|
-- Dragons@Work Digital Sovereignty Project
|
|
|
|
local cjson = require("cjson")
|
|
|
|
local MailRoute = {}
|
|
|
|
-- Load configuration
|
|
local config = require("config.server")
|
|
|
|
-- Validate email format
|
|
local function validate_email(email)
|
|
return email and email:match("^[^@]+@[^@]+%.[^@]+$") ~= nil
|
|
end
|
|
|
|
-- Validate required fields
|
|
local function validate_mail_data(data)
|
|
if not data.name or type(data.name) ~= "string" or data.name:match("^%s*$") then
|
|
return false, "Name is required and cannot be empty"
|
|
end
|
|
|
|
if not data.email or not validate_email(data.email) then
|
|
return false, "Valid email address is required"
|
|
end
|
|
|
|
if not data.message or type(data.message) ~= "string" or data.message:match("^%s*$") then
|
|
return false, "Message is required and cannot be empty"
|
|
end
|
|
|
|
-- Optional subject validation
|
|
if data.subject and (type(data.subject) ~= "string" or #data.subject > 200) then
|
|
return false, "Subject must be a string with max 200 characters"
|
|
end
|
|
|
|
-- Message length validation
|
|
if #data.message > 5000 then
|
|
return false, "Message too long (max 5000 characters)"
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
-- Generate unique request ID
|
|
local function generate_request_id()
|
|
return os.time() .. "-" .. math.random(1000, 9999)
|
|
end
|
|
|
|
-- Mail service handler
|
|
function MailRoute.handle_mail_send(request, server)
|
|
print("Mail endpoint called - Method: " .. request.method .. ", Path: " .. request.path)
|
|
print("Authenticated as: " .. request.auth.key_name .. " (" .. request.auth.api_key .. ")")
|
|
|
|
-- Basic request validation
|
|
if not request.body or request.body == "" then
|
|
return {error = "No request body", code = "MISSING_BODY"}
|
|
end
|
|
|
|
-- Parse JSON
|
|
local success, data = pcall(cjson.decode, request.body)
|
|
if not success then
|
|
return {error = "Invalid JSON", body = request.body, code = "INVALID_JSON"}
|
|
end
|
|
|
|
-- Validate mail data
|
|
local valid, error_message = validate_mail_data(data)
|
|
if not valid then
|
|
return {error = error_message, code = "VALIDATION_ERROR"}
|
|
end
|
|
|
|
-- Generate request ID for tracking
|
|
local request_id = generate_request_id()
|
|
|
|
-- Prepare email content
|
|
local subject = data.subject or "Contact Form Message"
|
|
local email_content = string.format(
|
|
"From: %s <%s>\nSubject: %s\n\n%s",
|
|
data.name, data.email, subject, data.message
|
|
)
|
|
|
|
-- Send email via SMTP
|
|
local SMTP = require("src.smtp")
|
|
local smtp_client = SMTP:new(config.mail)
|
|
|
|
local smtp_success, smtp_result = smtp_client:send_email(
|
|
config.mail.to_address,
|
|
subject,
|
|
email_content,
|
|
data.name
|
|
)
|
|
|
|
if smtp_success then
|
|
-- Success response
|
|
return {
|
|
success = true,
|
|
message = "Mail sent successfully",
|
|
request_id = request_id,
|
|
api_key_name = request.auth.key_name
|
|
}
|
|
else
|
|
-- SMTP error - log and return error
|
|
print("SMTP Error: " .. tostring(smtp_result))
|
|
return server:create_response(500, {
|
|
success = false,
|
|
error = "Failed to send email: " .. tostring(smtp_result),
|
|
request_id = request_id,
|
|
code = "SMTP_ERROR"
|
|
}, nil, nil, request)
|
|
end
|
|
end
|
|
|
|
return MailRoute
|
|
|