mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
Docs + flows work
This commit is contained in:
@@ -21,8 +21,6 @@ There is also an in-app Help / FAQ section that should be answering frequently a
|
|||||||
|
|
||||||
#### 🔝 Popular/Suggested
|
#### 🔝 Popular/Suggested
|
||||||
|
|
||||||
- [API endpoints details](/docs/API.md)
|
|
||||||
- [Plugin system details and how to develop your own](/front/plugins/README.md)
|
|
||||||
- [Network treemap configuration](/docs/NETWORK_TREE.md)
|
- [Network treemap configuration](/docs/NETWORK_TREE.md)
|
||||||
- [Gmail as SMTP server for sending emails](/docs/SMTP_GMAIL.md)
|
- [Gmail as SMTP server for sending emails](/docs/SMTP_GMAIL.md)
|
||||||
- [Subnets and VLANs configuration for arp-scan](/docs/SUBNETS.md)
|
- [Subnets and VLANs configuration for arp-scan](/docs/SUBNETS.md)
|
||||||
@@ -40,11 +38,17 @@ There is also an in-app Help / FAQ section that should be answering frequently a
|
|||||||
|
|
||||||
#### ♻ Misc
|
#### ♻ Misc
|
||||||
|
|
||||||
- [New Version notifications](/docs/VERSIONS.md)
|
|
||||||
- [Version history (legacy)](/docs/VERSIONS_HISTORY.md)
|
- [Version history (legacy)](/docs/VERSIONS_HISTORY.md)
|
||||||
- [Database structure](/docs/DATABASE.md)
|
|
||||||
- [Reverse proxy (Nginx, Apache, SWAG)](/docs/REVERSE_PROXY.md)
|
- [Reverse proxy (Nginx, Apache, SWAG)](/docs/REVERSE_PROXY.md)
|
||||||
|
|
||||||
|
#### 👩💻For Developers👨💻
|
||||||
|
|
||||||
|
- [APP code structure](/pialert/README.md)
|
||||||
|
- [Database structure](/docs/DATABASE.md)
|
||||||
|
- [API endpoints details](/docs/API.md)
|
||||||
|
- [Plugin system details and how to develop your own](/front/plugins/README.md)
|
||||||
|
- [New Version notifications](/docs/VERSIONS.md)
|
||||||
|
|
||||||
Feel free to suggest or submit new docs via a PR.
|
Feel free to suggest or submit new docs via a PR.
|
||||||
|
|
||||||
## 👨💻 Development priorities
|
## 👨💻 Development priorities
|
||||||
|
|||||||
0
front/flows.php
Normal file → Executable file
0
front/flows.php
Normal file → Executable file
@@ -312,7 +312,7 @@ function saveSettings()
|
|||||||
|
|
||||||
$temp = '['.$temp.']'; // wrap brackets
|
$temp = '['.$temp.']'; // wrap brackets
|
||||||
$txt .= $settingKey . "=" . $temp . "\n";
|
$txt .= $settingKey . "=" . $temp . "\n";
|
||||||
} elseif ($settingType == 'json') {
|
} elseif ($settingType == 'json' || substr($settingType, -9) === ".template") {
|
||||||
$txt .= $settingKey . "=" . $settingValue . "\n";
|
$txt .= $settingKey . "=" . $settingValue . "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -442,7 +442,7 @@
|
|||||||
"INCLUDED_SECTIONS_name" : "Notify on",
|
"INCLUDED_SECTIONS_name" : "Notify on",
|
||||||
"INCLUDED_SECTIONS_description" : "Specifies which events trigger notifications. Remove the event type(s) you don not want to get notified on. This setting overrides device-specific settings in the UI. (<code>CTRL + Click</code> to select/deselect).",
|
"INCLUDED_SECTIONS_description" : "Specifies which events trigger notifications. Remove the event type(s) you don not want to get notified on. This setting overrides device-specific settings in the UI. (<code>CTRL + Click</code> to select/deselect).",
|
||||||
"SCAN_CYCLE_MINUTES_name" : "Scan cycle delay",
|
"SCAN_CYCLE_MINUTES_name" : "Scan cycle delay",
|
||||||
"SCAN_CYCLE_MINUTES_description" : "The delay between scans in minutes. If using arp-scan, the scan time itself depends on the number of IP addresses to check. This is influenced by the network mask set in the <a href=\"#SCAN_SUBNETS\"><code>SCAN_SUBNETS</code> setting</a> at the top. Every IP takes a couple seconds to scan.",
|
"SCAN_CYCLE_MINUTES_description" : "The delay between scans in minutes. Only related to arp-scan, PiHole, DHCP_ACTIVE scans. If using arp-scan, the scan time itself depends on the number of IP addresses to check. This is influenced by the network mask set in the <a href=\"#SCAN_SUBNETS\"><code>SCAN_SUBNETS</code> setting</a> at the top. Every IP takes a couple seconds to scan.",
|
||||||
"DAYS_TO_KEEP_EVENTS_name" : "Delete events older than",
|
"DAYS_TO_KEEP_EVENTS_name" : "Delete events older than",
|
||||||
"DAYS_TO_KEEP_EVENTS_description" : "This is a maintenance setting. This specifies the number of days worth of event entries that will be kept. All older events will be deleted periodically. Also applies on Plugin Events History.",
|
"DAYS_TO_KEEP_EVENTS_description" : "This is a maintenance setting. This specifies the number of days worth of event entries that will be kept. All older events will be deleted periodically. Also applies on Plugin Events History.",
|
||||||
"HRS_TO_KEEP_NEWDEV_name" : "Keep new devices for",
|
"HRS_TO_KEEP_NEWDEV_name" : "Keep new devices for",
|
||||||
|
|||||||
@@ -34,12 +34,106 @@
|
|||||||
"name" : "dev_AlertEvents",
|
"name" : "dev_AlertEvents",
|
||||||
"type" : "setting",
|
"type" : "setting",
|
||||||
"value" : "KNWN_dev_AlertEvents"
|
"value" : "KNWN_dev_AlertEvents"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "trigger_ids",
|
||||||
|
"type" : "array",
|
||||||
|
"value" : "trigger.Object_PrimaryID"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "trigger_objects",
|
||||||
|
"type" : "array",
|
||||||
|
"value" : "trigger"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"settings":[
|
"settings":[
|
||||||
|
{
|
||||||
|
"function": "flows",
|
||||||
|
"type": "json",
|
||||||
|
"maxLength": 50,
|
||||||
|
"default_value": [{
|
||||||
|
"name":"apply_template",
|
||||||
|
"trigger": [
|
||||||
|
{
|
||||||
|
"object_event": "new",
|
||||||
|
"object_filter": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"step_type":"wait",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"days": 3,
|
||||||
|
"hours": 0,
|
||||||
|
"minutes": 0,
|
||||||
|
"seconds": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step_type":"condition",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"left": {
|
||||||
|
"value": "triggers[0].object['dev_NewDevice']",
|
||||||
|
"use_quotes": true,
|
||||||
|
"js_template": "'{value}'.toString()"
|
||||||
|
},
|
||||||
|
"operator": {
|
||||||
|
"value" : "==",
|
||||||
|
"data_type": "boolean"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"value": true,
|
||||||
|
"use_quotes": false,
|
||||||
|
"js_template": "'{value}'.toString()"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step_type":"action",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"type": "plugin",
|
||||||
|
"params":
|
||||||
|
{
|
||||||
|
"unique_prefix": "KNWN",
|
||||||
|
"overrides":[
|
||||||
|
{
|
||||||
|
"object_path": "settings.0",
|
||||||
|
"key":"function",
|
||||||
|
"value":"target_macs",
|
||||||
|
"target_property":"default_value",
|
||||||
|
"desired_value": "triggers.keys"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}],
|
||||||
|
"options": [],
|
||||||
|
"localized": ["name", "description"],
|
||||||
|
"name": [
|
||||||
|
{
|
||||||
|
"language_code": "en_us",
|
||||||
|
"string": "Flows"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": [
|
||||||
|
{
|
||||||
|
"language_code": "en_us",
|
||||||
|
"string": "The flow."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"function": "target_macs",
|
"function": "target_macs",
|
||||||
"type": "list.readonly",
|
"type": "list.readonly",
|
||||||
"maxLength": 50,
|
"maxLength": 50,
|
||||||
"default_value": [],
|
"default_value": [],
|
||||||
"options": [],
|
"options": [],
|
||||||
@@ -74,9 +168,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"function": "dev_Name",
|
"function": "dev_Name",
|
||||||
"type": "readonly",
|
"type": "text.template",
|
||||||
"maxLength": 50,
|
"maxLength": 50,
|
||||||
"default_value": "(unknown)",
|
"default_value": "(unknown)",
|
||||||
|
"value": {
|
||||||
|
"value":"(unknown)",
|
||||||
|
"override": true
|
||||||
|
},
|
||||||
"options": [],
|
"options": [],
|
||||||
"localized": ["name", "description"],
|
"localized": ["name", "description"],
|
||||||
"name": [
|
"name": [
|
||||||
|
|||||||
@@ -204,42 +204,34 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
|
|||||||
// Render different input types based on the settings type
|
// Render different input types based on the settings type
|
||||||
let input = "";
|
let input = "";
|
||||||
|
|
||||||
if (set['Type'] === 'text' || set['Type'] === 'string' || set['Type'] === 'date-time') {
|
const setType = set['Type'].toLowerCase();
|
||||||
input = `<input class="form-control" onChange="settingsChanged()" my-data-type="${set['Type']}" id="${set['Code_Name']}" value="${set['Value']}"/>`;
|
|
||||||
} else if (set['Type'] === 'password') {
|
if (setType.startsWith('text') || setType.startsWith('string') || setType.startsWith('date-time') ) {
|
||||||
input = `<input onChange="settingsChanged()" my-data-type="${set['Type']}" class="form-control input" id="${set['Code_Name']}" type="password" value="${set['Value']}"/>`;
|
|
||||||
} else if (set['Type'] === 'readonly') {
|
if(setType.includes(".select"))
|
||||||
input = `<input class="form-control input" my-data-type="${set['Type']}" id="${set['Code_Name']}" value="${set['Value']}" readonly/>`;
|
{
|
||||||
} else if (set['Type'] === 'boolean' || set['Type'] === 'integer.checkbox') {
|
input = generateInputOptions(set, input, isMultiSelect = false)
|
||||||
|
|
||||||
|
} else if(setType.includes(".multiselect"))
|
||||||
|
{
|
||||||
|
input = generateInputOptions(set, input, isMultiSelect = true)
|
||||||
|
} else{
|
||||||
|
input = `<input class="form-control" onChange="settingsChanged()" my-data-type="${setType}" id="${set['Code_Name']}" value="${set['Value']}"/>`;
|
||||||
|
}
|
||||||
|
} else if (setType === 'integer') {
|
||||||
|
input = `<input onChange="settingsChanged()" my-data-type="${setType}" class="form-control" id="${set['Code_Name']}" type="number" value="${set['Value']}"/>`;
|
||||||
|
} else if (setType === 'password') {
|
||||||
|
input = `<input onChange="settingsChanged()" my-data-type="${setType}" class="form-control input" id="${set['Code_Name']}" type="password" value="${set['Value']}"/>`;
|
||||||
|
} else if (setType === 'readonly') {
|
||||||
|
input = `<input class="form-control input" my-data-type="${setType}" id="${set['Code_Name']}" value="${set['Value']}" readonly/>`;
|
||||||
|
} else if (setType === 'boolean' || setType === 'integer.checkbox') {
|
||||||
let checked = set['Value'] === 'True' || set['Value'] === '1' ? 'checked' : '';
|
let checked = set['Value'] === 'True' || set['Value'] === '1' ? 'checked' : '';
|
||||||
input = `<input onChange="settingsChanged()" my-data-type="${set['Type']}" class="checkbox" id="${set['Code_Name']}" type="checkbox" value="${set['Value']}" ${checked} />`;
|
input = `<input onChange="settingsChanged()" my-data-type="${setType}" class="checkbox" id="${set['Code_Name']}" type="checkbox" value="${set['Value']}" ${checked} />`;
|
||||||
} else if (set['Type'] === 'integer') {
|
} else if (setType === 'integer.select') {
|
||||||
input = `<input onChange="settingsChanged()" my-data-type="${set['Type']}" class="form-control" id="${set['Code_Name']}" type="number" value="${set['Value']}"/>`;
|
|
||||||
} else if (set['Type'] === 'text.select' || set['Type'] === 'integer.select') {
|
|
||||||
input = `<select onChange="settingsChanged()" my-data-type="${set['Type']}" class="form-control" name="${set['Code_Name']}" id="${set['Code_Name']}">`;
|
|
||||||
|
|
||||||
values = createArray(set['Value']);
|
input = generateInputOptions(set, input)
|
||||||
options = createArray(set['Options']);
|
|
||||||
|
} else if (setType === 'subnets') {
|
||||||
options.forEach(option => {
|
|
||||||
let selected = values.includes(option) ? 'selected' : '';
|
|
||||||
input += `<option value="${option}" ${selected}>${option}</option>`;
|
|
||||||
});
|
|
||||||
|
|
||||||
input += '</select>';
|
|
||||||
} else if (set['Type'] === 'text.multiselect') {
|
|
||||||
input = `<select onChange="settingsChanged()" my-data-type="${set['Type']}" class="form-control" name="${set['Code_Name']}" id="${set['Code_Name']}" multiple>`;
|
|
||||||
|
|
||||||
values = createArray(set['Value']);
|
|
||||||
options = createArray(set['Options']);
|
|
||||||
|
|
||||||
options.forEach(option => {
|
|
||||||
let selected = values.includes(option) ? 'selected' : '';
|
|
||||||
input += `<option value="${option}" ${selected}>${option}</option>`;
|
|
||||||
});
|
|
||||||
|
|
||||||
input += '</select>';
|
|
||||||
} else if (set['Type'] === 'subnets') {
|
|
||||||
input = `
|
input = `
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
<div class="col-xs-5">
|
<div class="col-xs-5">
|
||||||
@@ -253,7 +245,7 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<select class="form-control" my-data-type="${set['Type']}" name="${set['Code_Name']}" id="${set['Code_Name']}" multiple readonly>`;
|
<select class="form-control" my-data-type="${setType}" name="${set['Code_Name']}" id="${set['Code_Name']}" multiple readonly>`;
|
||||||
|
|
||||||
|
|
||||||
options = createArray(set['Value']);
|
options = createArray(set['Value']);
|
||||||
@@ -264,7 +256,7 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
|
|||||||
|
|
||||||
input += '</select></div>' +
|
input += '</select></div>' +
|
||||||
'<div><button class="btn btn-primary" onclick="removeInterfaces()">Remove all</button></div>';
|
'<div><button class="btn btn-primary" onclick="removeInterfaces()">Remove all</button></div>';
|
||||||
} else if (set['Type'] === 'list') {
|
} else if (setType === 'list') {
|
||||||
|
|
||||||
settingKeyOfLists.push(set['Code_Name']);
|
settingKeyOfLists.push(set['Code_Name']);
|
||||||
|
|
||||||
@@ -278,8 +270,7 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<select class="form-control" my-data-type="${set['Type']}" name="${set['Code_Name']}" id="${set['Code_Name']}" multiple readonly>`;
|
<select class="form-control" my-data-type="${setType}" name="${set['Code_Name']}" id="${set['Code_Name']}" multiple readonly>`;
|
||||||
|
|
||||||
|
|
||||||
let options = createArray(set['Value']);
|
let options = createArray(set['Value']);
|
||||||
|
|
||||||
@@ -289,8 +280,8 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
|
|||||||
|
|
||||||
input += '</select></div>' +
|
input += '</select></div>' +
|
||||||
`<div><button class="btn btn-primary" my-input="${set['Code_Name']}" onclick="removeFromList(this)">Remove last</button></div>`;
|
`<div><button class="btn btn-primary" my-input="${set['Code_Name']}" onclick="removeFromList(this)">Remove last</button></div>`;
|
||||||
} else if (set['Type'] === 'json') {
|
} else if (setType === 'json') {
|
||||||
input = `<textarea class="form-control input" my-data-type="${set['Type']}" id="${set['Code_Name']}" readonly>${JSON.stringify(set['Value'], null, 2)}</textarea>`;
|
input = `<textarea class="form-control input" my-data-type="${setType}" id="${set['Code_Name']}" readonly>${JSON.stringify(set['Value'], null, 2)}</textarea>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
let eventsHtml = "";
|
let eventsHtml = "";
|
||||||
@@ -327,6 +318,26 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
function generateInputOptions(set, input, isMultiSelect = false)
|
||||||
|
{
|
||||||
|
|
||||||
|
multi = isMultiSelect ? "multiple" : "";
|
||||||
|
input = `<select onChange="settingsChanged()" my-data-type="${set['Type']}" class="form-control" name="${set['Code_Name']}" id="${set['Code_Name']}" ${multi}>`;
|
||||||
|
|
||||||
|
values = createArray(set['Value']);
|
||||||
|
options = createArray(set['Options']);
|
||||||
|
|
||||||
|
options.forEach(option => {
|
||||||
|
let selected = values.includes(option) ? 'selected' : '';
|
||||||
|
input += `<option value="${option}" ${selected}>${option}</option>`;
|
||||||
|
});
|
||||||
|
|
||||||
|
input += '</select>';
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
// todo fix
|
// todo fix
|
||||||
function createArray(input) {
|
function createArray(input) {
|
||||||
// Empty array
|
// Empty array
|
||||||
|
|||||||
0
pialert/flows.py
Normal file → Executable file
0
pialert/flows.py
Normal file → Executable file
@@ -283,6 +283,7 @@ def plugin_param_from_glob_set(globalSetting):
|
|||||||
|
|
||||||
noConversion = ['text', 'string', 'integer', 'boolean', 'password', 'readonly', 'integer.select', 'text.select', 'integer.checkbox' ]
|
noConversion = ['text', 'string', 'integer', 'boolean', 'password', 'readonly', 'integer.select', 'text.select', 'integer.checkbox' ]
|
||||||
arrayConversion = ['text.multiselect', 'list']
|
arrayConversion = ['text.multiselect', 'list']
|
||||||
|
jsonConversion = ['.template']
|
||||||
|
|
||||||
if setTyp in noConversion:
|
if setTyp in noConversion:
|
||||||
return setVal
|
return setVal
|
||||||
@@ -290,6 +291,12 @@ def plugin_param_from_glob_set(globalSetting):
|
|||||||
if setTyp in arrayConversion:
|
if setTyp in arrayConversion:
|
||||||
return flatten_array(setVal)
|
return flatten_array(setVal)
|
||||||
|
|
||||||
|
for item in jsonConversion:
|
||||||
|
if setTyp.endswith(item):
|
||||||
|
return json.dumps(setVal)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Gets the setting value
|
# Gets the setting value
|
||||||
def get_plugin_setting_value(plugin, function_key):
|
def get_plugin_setting_value(plugin, function_key):
|
||||||
|
|||||||
Reference in New Issue
Block a user