secubox-openwrt/package/secubox/luci-app-bandwidth-manager/htdocs/luci-static/resources/view/bandwidth-manager/parental-controls.js
CyberMind-FR e58f479cd4 feat(waf): Update WAF scenarios with 2024-2025 CVEs and OWASP threats
Add detection patterns for latest actively exploited vulnerabilities:
- CVE-2025-55182 (React2Shell, CVSS 10.0)
- CVE-2025-8110 (Gogs RCE), CVE-2025-53770 (SharePoint)
- CVE-2025-52691 (SmarterMail), CVE-2025-40551 (SolarWinds)
- CVE-2024-47575 (FortiManager), CVE-2024-21887 (Ivanti)
- CVE-2024-3400, CVE-2024-0012, CVE-2024-9474 (PAN-OS)

New attack categories based on OWASP Top 10 2025:
- HTTP Request Smuggling (TE.CL/CL.TE conflicts)
- AI/LLM Prompt Injection (ChatML, instruction markers)
- WAF Bypass techniques (Unicode normalization, double encoding)
- Supply Chain attacks (CI/CD poisoning, dependency confusion)
- Extended SSTI (Jinja2, Freemarker, Velocity, Thymeleaf)
- API Abuse (BOLA/IDOR, mass assignment)

CrowdSec scenarios split into 11 separate files for reliability.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-12 05:02:57 +01:00

549 lines
22 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
'require view';
'require ui';
'require rpc';
'require bandwidth-manager/api as API';
'require secubox/kiss-theme';
var PRESET_ICONS = {
'moon': '🌙',
'book': '📚',
'users': '👨‍👩‍👧‍👦',
'clock': '⏰',
'shield': '🛡️',
'ban': '🚫'
};
var DAYS = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
var DAY_LABELS = { 'mon': 'M', 'tue': 'T', 'wed': 'W', 'thu': 'T', 'fri': 'F', 'sat': 'S', 'sun': 'S' };
return L.view.extend({
load: function() {
return Promise.all([
API.listPresetModes(),
API.listParentalSchedules(),
API.getFilterCategories(),
API.listGroups(),
API.getUsageRealtime()
]);
},
render: function(data) {
var presets = (data[0] && data[0].presets) || [];
var schedules = (data[1] && data[1].schedules) || [];
var categories = (data[2] && data[2].categories) || [];
var groups = (data[3] && data[3].groups) || [];
var clients = (data[4] && data[4].clients) || [];
var self = this;
var v = E('div', { 'class': 'cbi-map' }, [
E('link', { 'rel': 'stylesheet', 'href': L.resource('bandwidth-manager/dashboard.css') }),
E('link', { 'rel': 'stylesheet', 'href': L.resource('bandwidth-manager/parental.css') }),
E('style', {}, this.getCustomStyles()),
E('h2', {}, _('Parental Controls')),
E('div', { 'class': 'cbi-map-descr' }, _('Manage internet access schedules, content filtering, and quick preset modes for family devices'))
]);
// Quick Preset Modes
var presetsSection = E('div', { 'class': 'cbi-section' }, [
E('h3', {}, _('Quick Preset Modes')),
E('p', { 'class': 'section-desc' }, _('Activate a preset to instantly apply predefined rules. Only one preset can be active at a time.'))
]);
var presetsGrid = E('div', { 'class': 'presets-grid' });
// Add default presets if none exist
var displayPresets = presets.length > 0 ? presets : [
{ id: 'preset_bedtime', name: 'Bedtime', icon: 'moon', enabled: false, action: 'block', blocked_categories: 'all', builtin: true },
{ id: 'preset_homework', name: 'Homework', icon: 'book', enabled: false, action: 'filter', allowed_categories: 'education reference', blocked_categories: 'gaming social streaming', builtin: true },
{ id: 'preset_family', name: 'Family Time', icon: 'users', enabled: false, action: 'filter', allowed_categories: 'streaming education', blocked_categories: 'adult gambling', builtin: true }
];
displayPresets.forEach(function(preset) {
var icon = PRESET_ICONS[preset.icon] || PRESET_ICONS['clock'];
var presetCard = E('div', {
'class': 'preset-card' + (preset.enabled ? ' active' : ''),
'data-preset-id': preset.id
}, [
E('div', { 'class': 'preset-icon' }, icon),
E('div', { 'class': 'preset-name' }, preset.name),
E('div', { 'class': 'preset-action' }, preset.action === 'block' ? _('Blocks all access') : _('Content filtered')),
E('label', { 'class': 'preset-toggle' }, [
E('input', {
'type': 'checkbox',
'checked': preset.enabled,
'change': function(ev) { self.togglePreset(preset.id, ev.target.checked); }
}),
E('span', { 'class': 'toggle-slider' })
])
]);
presetsGrid.appendChild(presetCard);
});
presetsSection.appendChild(presetsGrid);
v.appendChild(presetsSection);
// Schedules Section
var schedulesSection = E('div', { 'class': 'cbi-section' }, [
E('h3', {}, _('Access Schedules')),
E('div', { 'class': 'section-actions' }, [
E('button', {
'class': 'bw-btn bw-btn-primary',
'click': function() { self.showCreateScheduleModal(groups, clients); }
}, [E('span', {}, '+'), ' ' + _('Add Schedule')])
])
]);
if (schedules.length > 0) {
var schedulesGrid = E('div', { 'class': 'schedules-grid' });
schedules.forEach(function(schedule) {
var daysArray = (schedule.days || '').split(' ').filter(Boolean);
var scheduleCard = E('div', {
'class': 'schedule-card' + (schedule.active ? ' active-now' : ''),
'data-schedule-id': schedule.id
}, [
E('div', { 'class': 'schedule-header' }, [
E('div', { 'class': 'schedule-info' }, [
E('div', { 'class': 'schedule-name' }, schedule.name),
E('div', { 'class': 'schedule-target' }, [
E('span', { 'class': 'target-type' }, schedule.target_type === 'group' ? '👥' : '📱'),
' ' + schedule.target
])
]),
E('label', { 'class': 'schedule-toggle' }, [
E('input', {
'type': 'checkbox',
'checked': schedule.enabled,
'change': function(ev) { self.toggleSchedule(schedule.id, ev.target.checked); }
}),
E('span', { 'class': 'toggle-slider' })
])
]),
E('div', { 'class': 'schedule-time' }, [
E('span', { 'class': 'time-icon' }, '⏰'),
E('span', {}, schedule.start_time + ' - ' + schedule.end_time)
]),
E('div', { 'class': 'schedule-days' },
DAYS.map(function(day) {
return E('span', {
'class': 'day-badge' + (daysArray.indexOf(day) !== -1 ? ' active' : '')
}, DAY_LABELS[day]);
})
),
E('div', { 'class': 'schedule-action-badge' }, [
schedule.action === 'block' ?
E('span', { 'class': 'badge badge-danger' }, '🚫 ' + _('Block')) :
E('span', { 'class': 'badge badge-warning' }, '⚠️ ' + _('Throttle'))
]),
schedule.active ? E('div', { 'class': 'active-indicator' }, _('Active Now')) : null,
E('div', { 'class': 'schedule-actions' }, [
E('button', {
'class': 'bw-btn bw-btn-secondary btn-sm',
'click': function() { self.showEditScheduleModal(schedule, groups, clients); }
}, _('Edit')),
E('button', {
'class': 'bw-btn bw-btn-secondary btn-sm btn-danger',
'click': function() { self.deleteSchedule(schedule); }
}, _('Delete'))
])
].filter(Boolean));
schedulesGrid.appendChild(scheduleCard);
});
schedulesSection.appendChild(schedulesGrid);
} else {
schedulesSection.appendChild(E('div', { 'class': 'empty-state' }, [
E('div', { 'class': 'empty-icon' }, '📅'),
E('p', {}, _('No schedules configured')),
E('p', { 'class': 'empty-hint' }, _('Create schedules to automatically control internet access during specific times'))
]));
}
v.appendChild(schedulesSection);
// Weekly Schedule Visual
var weeklySection = E('div', { 'class': 'cbi-section' }, [
E('h3', {}, _('Weekly Overview')),
this.renderWeeklyGrid(schedules)
]);
v.appendChild(weeklySection);
// Content Filter Categories
var filterSection = E('div', { 'class': 'cbi-section' }, [
E('h3', {}, _('Content Filter Categories')),
E('p', { 'class': 'section-desc' }, _('Categories that can be blocked or allowed in schedules and presets'))
]);
var categoriesGrid = E('div', { 'class': 'categories-grid' });
categories.forEach(function(cat) {
categoriesGrid.appendChild(E('div', { 'class': 'category-badge' }, [
E('span', { 'class': 'category-icon' }, self.getCategoryIcon(cat.id)),
E('span', {}, cat.name)
]));
});
filterSection.appendChild(categoriesGrid);
v.appendChild(filterSection);
return KissTheme.wrap([v], 'admin/services/bandwidth-manager/parental-controls');
},
togglePreset: function(presetId, enabled) {
var self = this;
API.activatePresetMode(presetId, enabled ? 1 : 0).then(function(result) {
if (result.success) {
ui.addNotification(null, E('p', enabled ? _('Preset activated') : _('Preset deactivated')), 'success');
window.location.reload();
} else {
ui.addNotification(null, E('p', result.message || _('Failed to toggle preset')), 'error');
}
});
},
toggleSchedule: function(scheduleId, enabled) {
API.toggleParentalSchedule(scheduleId, enabled ? 1 : 0).then(function(result) {
if (result.success) {
ui.addNotification(null, E('p', _('Schedule updated')), 'success');
} else {
ui.addNotification(null, E('p', result.message || _('Failed to update schedule')), 'error');
}
});
},
showCreateScheduleModal: function(groups, clients) {
var self = this;
var targetOptions = [];
clients.forEach(function(c) {
targetOptions.push(E('option', { 'value': c.mac, 'data-type': 'device' }, '📱 ' + (c.hostname || c.mac)));
});
groups.forEach(function(g) {
targetOptions.push(E('option', { 'value': g.id, 'data-type': 'group' }, '👥 ' + g.name));
});
var body = E('div', { 'class': 'schedule-form' }, [
E('div', { 'class': 'form-group' }, [
E('label', {}, _('Schedule Name')),
E('input', { 'type': 'text', 'id': 'schedule-name', 'class': 'cbi-input-text', 'placeholder': _('e.g., Bedtime for Kids') })
]),
E('div', { 'class': 'form-group' }, [
E('label', {}, _('Apply To')),
E('select', { 'id': 'schedule-target', 'class': 'cbi-input-select' }, targetOptions)
]),
E('div', { 'class': 'form-group' }, [
E('label', {}, _('Action')),
E('select', { 'id': 'schedule-action', 'class': 'cbi-input-select' }, [
E('option', { 'value': 'block' }, _('Block Internet Access')),
E('option', { 'value': 'throttle' }, _('Throttle Bandwidth'))
])
]),
E('div', { 'class': 'form-row' }, [
E('div', { 'class': 'form-group half' }, [
E('label', {}, _('Start Time')),
E('input', { 'type': 'time', 'id': 'schedule-start', 'class': 'cbi-input-text', 'value': '21:00' })
]),
E('div', { 'class': 'form-group half' }, [
E('label', {}, _('End Time')),
E('input', { 'type': 'time', 'id': 'schedule-end', 'class': 'cbi-input-text', 'value': '07:00' })
])
]),
E('div', { 'class': 'form-group' }, [
E('label', {}, _('Days')),
E('div', { 'class': 'days-selector' },
DAYS.map(function(day) {
return E('label', { 'class': 'day-checkbox' }, [
E('input', { 'type': 'checkbox', 'value': day, 'checked': ['mon', 'tue', 'wed', 'thu', 'fri'].indexOf(day) !== -1 }),
E('span', {}, DAY_LABELS[day])
]);
})
)
])
]);
ui.showModal(_('Create Schedule'), [
body,
E('div', { 'class': 'right' }, [
E('button', { 'class': 'btn', 'click': ui.hideModal }, _('Cancel')),
' ',
E('button', {
'class': 'btn cbi-button-action',
'click': function() { self.createSchedule(); }
}, _('Create'))
])
]);
},
createSchedule: function() {
var name = document.getElementById('schedule-name').value;
var targetSelect = document.getElementById('schedule-target');
var target = targetSelect.value;
var targetType = targetSelect.options[targetSelect.selectedIndex].getAttribute('data-type');
var action = document.getElementById('schedule-action').value;
var startTime = document.getElementById('schedule-start').value;
var endTime = document.getElementById('schedule-end').value;
var days = [];
document.querySelectorAll('.days-selector input:checked').forEach(function(cb) {
days.push(cb.value);
});
if (!name) {
ui.addNotification(null, E('p', _('Schedule name is required')), 'error');
return;
}
if (days.length === 0) {
ui.addNotification(null, E('p', _('Select at least one day')), 'error');
return;
}
API.createParentalSchedule(name, targetType, target, action, startTime, endTime, days.join(' ')).then(function(result) {
if (result.success) {
ui.hideModal();
ui.addNotification(null, E('p', _('Schedule created')), 'success');
window.location.reload();
} else {
ui.addNotification(null, E('p', result.message || _('Failed to create schedule')), 'error');
}
});
},
showEditScheduleModal: function(schedule, groups, clients) {
var self = this;
var daysArray = (schedule.days || '').split(' ').filter(Boolean);
var targetOptions = [];
clients.forEach(function(c) {
targetOptions.push(E('option', {
'value': c.mac,
'data-type': 'device',
'selected': schedule.target === c.mac
}, '📱 ' + (c.hostname || c.mac)));
});
groups.forEach(function(g) {
targetOptions.push(E('option', {
'value': g.id,
'data-type': 'group',
'selected': schedule.target === g.id
}, '👥 ' + g.name));
});
var body = E('div', { 'class': 'schedule-form' }, [
E('div', { 'class': 'form-group' }, [
E('label', {}, _('Schedule Name')),
E('input', { 'type': 'text', 'id': 'edit-schedule-name', 'class': 'cbi-input-text', 'value': schedule.name })
]),
E('div', { 'class': 'form-group' }, [
E('label', {}, _('Apply To')),
E('select', { 'id': 'edit-schedule-target', 'class': 'cbi-input-select' }, targetOptions)
]),
E('div', { 'class': 'form-group' }, [
E('label', {}, _('Action')),
E('select', { 'id': 'edit-schedule-action', 'class': 'cbi-input-select' }, [
E('option', { 'value': 'block', 'selected': schedule.action === 'block' }, _('Block Internet Access')),
E('option', { 'value': 'throttle', 'selected': schedule.action === 'throttle' }, _('Throttle Bandwidth'))
])
]),
E('div', { 'class': 'form-row' }, [
E('div', { 'class': 'form-group half' }, [
E('label', {}, _('Start Time')),
E('input', { 'type': 'time', 'id': 'edit-schedule-start', 'class': 'cbi-input-text', 'value': schedule.start_time })
]),
E('div', { 'class': 'form-group half' }, [
E('label', {}, _('End Time')),
E('input', { 'type': 'time', 'id': 'edit-schedule-end', 'class': 'cbi-input-text', 'value': schedule.end_time })
])
]),
E('div', { 'class': 'form-group' }, [
E('label', {}, _('Days')),
E('div', { 'class': 'days-selector' },
DAYS.map(function(day) {
return E('label', { 'class': 'day-checkbox' }, [
E('input', { 'type': 'checkbox', 'value': day, 'checked': daysArray.indexOf(day) !== -1 }),
E('span', {}, DAY_LABELS[day])
]);
})
)
])
]);
ui.showModal(_('Edit Schedule'), [
body,
E('div', { 'class': 'right' }, [
E('button', { 'class': 'btn', 'click': ui.hideModal }, _('Cancel')),
' ',
E('button', {
'class': 'btn cbi-button-action',
'click': function() { self.updateSchedule(schedule.id); }
}, _('Save'))
])
]);
},
updateSchedule: function(scheduleId) {
var name = document.getElementById('edit-schedule-name').value;
var targetSelect = document.getElementById('edit-schedule-target');
var target = targetSelect.value;
var targetType = targetSelect.options[targetSelect.selectedIndex].getAttribute('data-type');
var action = document.getElementById('edit-schedule-action').value;
var startTime = document.getElementById('edit-schedule-start').value;
var endTime = document.getElementById('edit-schedule-end').value;
var days = [];
document.querySelectorAll('.days-selector input:checked').forEach(function(cb) {
days.push(cb.value);
});
API.updateParentalSchedule(scheduleId, name, targetType, target, action, startTime, endTime, days.join(' '), 1).then(function(result) {
if (result.success) {
ui.hideModal();
ui.addNotification(null, E('p', _('Schedule updated')), 'success');
window.location.reload();
} else {
ui.addNotification(null, E('p', result.message || _('Failed to update schedule')), 'error');
}
});
},
deleteSchedule: function(schedule) {
if (!confirm(_('Delete schedule "%s"?').format(schedule.name))) {
return;
}
API.deleteParentalSchedule(schedule.id).then(function(result) {
if (result.success) {
ui.addNotification(null, E('p', _('Schedule deleted')), 'success');
window.location.reload();
} else {
ui.addNotification(null, E('p', result.message || _('Failed to delete schedule')), 'error');
}
});
},
renderWeeklyGrid: function(schedules) {
var hours = [];
for (var i = 0; i < 24; i++) {
hours.push(i);
}
var grid = E('div', { 'class': 'weekly-grid' }, [
E('div', { 'class': 'grid-header' }, [
E('div', { 'class': 'grid-corner' }),
hours.map(function(h) {
return E('div', { 'class': 'hour-label' }, h % 6 === 0 ? String(h).padStart(2, '0') : '');
})
].flat())
]);
var self = this;
DAYS.forEach(function(day, dayIndex) {
var row = E('div', { 'class': 'grid-row' }, [
E('div', { 'class': 'day-label' }, DAY_LABELS[day])
]);
hours.forEach(function(hour) {
var isBlocked = false;
schedules.forEach(function(s) {
if (!s.enabled) return;
var daysArray = (s.days || '').split(' ');
if (daysArray.indexOf(day) === -1) return;
var start = parseInt(s.start_time.split(':')[0]);
var end = parseInt(s.end_time.split(':')[0]);
if (start < end) {
if (hour >= start && hour < end) isBlocked = true;
} else {
if (hour >= start || hour < end) isBlocked = true;
}
});
row.appendChild(E('div', {
'class': 'hour-cell' + (isBlocked ? ' blocked' : '')
}));
});
grid.appendChild(row);
});
return grid;
},
getCategoryIcon: function(catId) {
var icons = {
'adult': '🔞', 'gambling': '🎰', 'gaming': '🎮', 'social': '💬',
'streaming': '📺', 'education': '📚', 'news': '📰', 'shopping': '🛒',
'finance': '💰', 'health': '🏥', 'travel': '', 'technology': '💻',
'sports': '', 'entertainment': '🎬', 'reference': '📖', 'downloads': '📥'
};
return icons[catId] || '📁';
},
getCustomStyles: function() {
return `
.section-desc { color: #999; font-size: 14px; margin-bottom: 16px; }
.section-actions { margin-bottom: 16px; }
.presets-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 16px; }
.preset-card { background: var(--bw-light, #15151a); border: 2px solid var(--bw-border, #25252f); border-radius: 12px; padding: 20px; text-align: center; transition: all 0.2s; }
.preset-card.active { border-color: #10b981; background: rgba(16, 185, 129, 0.1); }
.preset-icon { font-size: 48px; margin-bottom: 12px; }
.preset-name { font-size: 18px; font-weight: 600; color: #fff; margin-bottom: 4px; }
.preset-action { font-size: 12px; color: #999; margin-bottom: 16px; }
.preset-toggle, .schedule-toggle { position: relative; display: inline-block; width: 48px; height: 24px; }
.preset-toggle input, .schedule-toggle input { opacity: 0; width: 0; height: 0; }
.toggle-slider { position: absolute; cursor: pointer; inset: 0; background: var(--bw-border, #25252f); border-radius: 24px; transition: 0.3s; }
.toggle-slider::before { content: ""; position: absolute; width: 18px; height: 18px; left: 3px; bottom: 3px; background: #fff; border-radius: 50%; transition: 0.3s; }
input:checked + .toggle-slider { background: #10b981; }
input:checked + .toggle-slider::before { transform: translateX(24px); }
.schedules-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
.schedule-card { background: var(--bw-light, #15151a); border: 1px solid var(--bw-border, #25252f); border-radius: 12px; padding: 16px; position: relative; }
.schedule-card.active-now { border-color: #f59e0b; }
.schedule-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px; }
.schedule-name { font-size: 16px; font-weight: 600; color: #fff; }
.schedule-target { font-size: 13px; color: #999; margin-top: 4px; }
.schedule-time { display: flex; align-items: center; gap: 8px; font-size: 14px; color: #ccc; margin-bottom: 12px; }
.time-icon { font-size: 16px; }
.schedule-days { display: flex; gap: 4px; margin-bottom: 12px; }
.day-badge { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600; background: var(--bw-dark, #0a0a0f); color: #666; border: 1px solid var(--bw-border, #25252f); }
.day-badge.active { background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%); color: white; border: none; }
.schedule-action-badge { margin-bottom: 12px; }
.badge { padding: 4px 10px; border-radius: 4px; font-size: 11px; font-weight: 600; }
.badge-danger { background: rgba(239, 68, 68, 0.2); color: #f87171; }
.badge-warning { background: rgba(245, 158, 11, 0.2); color: #fbbf24; }
.active-indicator { position: absolute; top: 12px; right: 12px; font-size: 11px; color: #f59e0b; font-weight: 600; animation: pulse 2s infinite; }
.schedule-actions { display: flex; gap: 8px; }
.btn-sm { padding: 6px 12px; font-size: 12px; }
.btn-danger { color: #ef4444; }
.empty-state { text-align: center; padding: 40px; color: #999; }
.empty-icon { font-size: 64px; margin-bottom: 16px; opacity: 0.5; }
.empty-hint { font-size: 13px; color: #666; }
.weekly-grid { background: var(--bw-light, #15151a); border: 1px solid var(--bw-border, #25252f); border-radius: 8px; overflow: hidden; }
.grid-header, .grid-row { display: flex; }
.grid-corner, .day-label { width: 40px; flex-shrink: 0; padding: 8px; font-size: 11px; font-weight: 600; color: #999; display: flex; align-items: center; justify-content: center; }
.hour-label { flex: 1; padding: 4px; font-size: 10px; color: #666; text-align: center; }
.hour-cell { flex: 1; height: 20px; background: var(--bw-dark, #0a0a0f); border: 1px solid var(--bw-border, #25252f); }
.hour-cell.blocked { background: rgba(239, 68, 68, 0.4); }
.categories-grid { display: flex; flex-wrap: wrap; gap: 8px; }
.category-badge { display: flex; align-items: center; gap: 6px; padding: 8px 12px; background: var(--bw-light, #15151a); border: 1px solid var(--bw-border, #25252f); border-radius: 6px; font-size: 13px; color: #ccc; }
.category-icon { font-size: 16px; }
.form-group { margin-bottom: 16px; }
.form-group label { display: block; margin-bottom: 6px; font-weight: 500; color: #ccc; }
.form-row { display: flex; gap: 16px; }
.form-group.half { flex: 1; }
.days-selector { display: flex; gap: 8px; }
.day-checkbox { display: flex; flex-direction: column; align-items: center; cursor: pointer; }
.day-checkbox input { margin-bottom: 4px; }
.day-checkbox span { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; background: var(--bw-dark, #0a0a0f); border: 1px solid var(--bw-border, #25252f); border-radius: 50%; font-size: 12px; font-weight: 600; color: #666; }
.day-checkbox input:checked + span { background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%); color: white; border: none; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
`;
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});