import { ZikoUIFlex } from "../../custom-elements/Flex"; class ZikoUIForm extends ZikoUIFlex { constructor(...items) { super("form", "Form"); this.append(...items); this.setMethod("POST"); // this.setAction("/"); // this.addCSRFToken(); // Add CSRF token field by default } setAction(action = "/") { // Ensure the action URL is trusted before setting it if (this.isTrustedURL(action)) { this.setAttr("action", action); } else { throw new Error('Untrusted action URL.'); } return this; } setMethod(method = "post") { const validMethods = ["post", "get"]; if (validMethods.includes(method.toLowerCase())) { this.setAttr("method", method); } else { throw new Error('Invalid HTTP method.'); } return this; } get data() { const formData = new FormData(this.element); this.items.forEach(n => { if (n.isInput || n.isSelect || n.isTextarea) { // Sanitize input values before appending formData.append(n.element.name, this.#sanitizeInput(n.value)); } }); return formData; } // Sanitize input data to prevent XSS #sanitizeInput(input) { const div = document?.createElement('div'); div.textContent = input; return div.innerHTML; } // Include a CSRF token in the form addCSRFToken() { const token = this.getCSRFTokenFromServer(); const hiddenInput = document?.createElement('input'); hiddenInput.type = 'hidden'; hiddenInput.name = 'csrf_token'; hiddenInput.value = token; this.element?.append(hiddenInput); } // Method to fetch CSRF token from the server (mocked here) getCSRFTokenFromServer() { // Replace with real token fetching logic return 'mocked_csrf_token'; } sendFormData() { fetch(this.element.action, { method: this.element.method, body: this.data, headers: { 'X-CSRF-Token': this.getByName('csrf_token'), // Add CSRF token header } }) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => console.log('Success:', data)) .catch(error => { console.error('Error:', error.message || error); }); return this; } getByName(name) { return this.data.get(name); } // Check if the action URL is trusted isTrustedURL(url) { const trustedDomains = ['/','yourdomain.com', 'anothertrustedsite.com']; try { const urlObj = new URL(url); return trustedDomains.includes(urlObj.hostname); } catch (e) { return false; } } } const Form = (...items) => new ZikoUIForm(...items); export { Form, ZikoUIForm };