ziko
Version:
a versatile javaScript framework offering a rich set of UI components, advanced mathematical utilities, reactivity, animations, client side routing and graphics capabilities
105 lines (96 loc) • 3.19 kB
Plain Text
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
};