Skip to content

Commit

Permalink
#136 added IP parameter type + fixed some small issues
Browse files Browse the repository at this point in the history
  • Loading branch information
bugy committed Dec 28, 2018
1 parent d126830 commit 08fc1b3
Show file tree
Hide file tree
Showing 8 changed files with 334 additions and 40 deletions.
16 changes: 16 additions & 0 deletions samples/configs/parameterized.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,22 @@
"constant": true,
"param": "--audit_name",
"default": "${auth.audit_name}"
},
{
"name": "Any IP",
"param": "--any_ip",
"type": "ip"
},
{
"name": "IP v4",
"param": "--ip4",
"type": "ip4",
"default": "127.0.0.1"
},
{
"name": "IP v6",
"param": "--ip6",
"type": "ip6"
}
]
}
23 changes: 22 additions & 1 deletion src/model/script_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import os
import re
from ipaddress import ip_address, IPv4Address, IPv6Address

from auth.authorization import ANY_USER
from config.script.list_values import ConstValuesProvider, ScriptValuesProvider, EmptyValuesProvider, \
Expand Down Expand Up @@ -270,7 +271,7 @@ def _reload(self):
self.separator = config.get('separator', ',')
self.multiple_arguments = read_boolean('multiple_arguments', config, default=False)
self.default = _resolve_default(config.get('default'), self._username, self._audit_name)
self.type = config.get('type', 'text')
self.type = self._read_type(config)

constant = read_boolean('constant', config, False)
if constant and not self.default:
Expand All @@ -288,6 +289,14 @@ def _reload(self):
self._values_provider = values_provider
self._reload_values()

def _read_type(self, config):
type = config.get('type', 'text')

if type.lower() in ('ip', 'ip4', 'ip6', 'ipv4', 'ipv6'):
type = type.lower().replace('v', '')

return type

def _param_values_observer(self, key, old_value, new_value):
values_provider = self._values_provider
if values_provider is None:
Expand Down Expand Up @@ -380,6 +389,18 @@ def validate_value(self, value, *, ignore_required=False):
+ value_string + ' < ' + str(self.min) + ')'
return None

if self.type in ('ip', 'ip4', 'ip6'):
try:
address = ip_address(value.strip())
if self.type == 'ip4':
if not isinstance(address, IPv4Address):
return value_string + ' is not an IPv4 address'
elif self.type == 'ip6':
if not isinstance(address, IPv6Address):
return value_string + ' is not an IPv6 address'
except ValueError:
return 'wrong IP address ' + value_string

allowed_values = self.values

if self.type == 'list':
Expand Down
56 changes: 54 additions & 2 deletions src/tests/script_config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,18 @@ def test_allowed_values_for_non_list(self):
'values': {'script': 'echo "123\n" "456"'}})
self.assertEqual(None, parameter_model.values)

def test_ip_uppercase(self):
parameter_model = _create_parameter_model({
'name': 'def_param',
'type': 'IP'})
self.assertEqual('ip', parameter_model.type)

def test_ip_with_v(self):
parameter_model = _create_parameter_model({
'name': 'def_param',
'type': 'Ipv6'})
self.assertEqual('ip6', parameter_model.type)


class ParameterModelDependantValuesTest(unittest.TestCase):
def test_get_parameter_values_simple(self):
Expand Down Expand Up @@ -866,9 +878,9 @@ def test_multiselect_when_single_not_matching_element(self):
self.assert_error(error)

def test_list_with_script_when_matches(self):
parameter = create_parameter_model('param', type=list, values_script="echo '123\n' 'abc'")
parameter = create_parameter_model('param', type='list', values_script="echo '123\n' 'abc'")

error = parameter.validate_value('abc')
error = parameter.validate_value('123')
self.assertIsNone(error)

def test_list_with_dependency_when_matches(self):
Expand All @@ -886,6 +898,46 @@ def test_list_with_dependency_when_matches(self):
error = parameter.validate_value(' _abc_')
self.assertIsNone(error)

def test_any_ip_when_ip4(self):
parameter = create_parameter_model('param', type='ip')
error = parameter.validate_value('127.0.0.1')
self.assertIsNone(error)

def test_any_ip_when_ip6(self):
parameter = create_parameter_model('param', type='ip')
error = parameter.validate_value('ABCD::6789')
self.assertIsNone(error)

def test_any_ip_when_wrong(self):
parameter = create_parameter_model('param', type='ip')
error = parameter.validate_value('127.abcd.1')
self.assert_error(error)

def test_ip4_when_valid(self):
parameter = create_parameter_model('param', type='ip4')
error = parameter.validate_value('192.168.0.13')
self.assertIsNone(error)

def test_ip4_when_ip6(self):
parameter = create_parameter_model('param', type='ip4')
error = parameter.validate_value('ABCD::1234')
self.assert_error(error)

def test_ip6_when_valid(self):
parameter = create_parameter_model('param', type='ip6')
error = parameter.validate_value('1:2:3:4:5:6:7:8')
self.assertIsNone(error)

def test_ip6_when_ip4(self):
parameter = create_parameter_model('param', type='ip6')
error = parameter.validate_value('172.13.0.15')
self.assert_error(error)

def test_ip6_when_complex_valid(self):
parameter = create_parameter_model('param', type='ip6')
error = parameter.validate_value('AbC:0::13:127.0.0.1')
self.assertIsNone(error)

def assert_error(self, error):
self.assertFalse(is_blank(error), 'Expected validation error, but validation passed')

Expand Down
10 changes: 0 additions & 10 deletions web-src/js/components/file_upload.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,6 @@
return this.value.name;
},
fieldType() {
if (this.config.type === 'int') {
return 'number';
} else if (this.config.secure) {
return 'password';
}
return 'text';
}
},
mounted: function () {
Expand Down
105 changes: 95 additions & 10 deletions web-src/js/components/textfield.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
var empty = isEmptyString(value) || isEmptyString(value.trim());
if ((textField.validity.badInput)) {
return getInvalidTypeError(this.type);
return getInvalidTypeError(this.config.type);
}
if (this.config.required && empty) {
Expand Down Expand Up @@ -114,17 +114,17 @@
function getValidByTypeError(value, type, min, max) {
if (type === 'int') {
var isInteger = /^(((\-?[1-9])(\d*))|0)$/.test(value);
const isInteger = /^(((-?[1-9])(\d*))|0)$/.test(value);
if (!isInteger) {
return getInvalidTypeError(type);
}
var intValue = parseInt(value);
var minMaxValid = true;
var minMaxError = "";
var minMaxError = '';
if (!isNull(min)) {
minMaxError += "min: " + min;
minMaxError += 'min: ' + min;
if (intValue < parseInt(min)) {
minMaxValid = false;
Expand All @@ -137,27 +137,112 @@
}
if (!isEmptyString(minMaxError)) {
minMaxError += ", ";
minMaxError += ', ';
}
minMaxError += "max: " + max;
minMaxError += 'max: ' + max;
}
if (!minMaxValid) {
return minMaxError;
}
return "";
return '';
} else if (type === 'ip') {
if (isEmptyString(validateIp4(value)) || isEmptyString(validateIp6(value))) {
return ''
}
return 'IPv4 or IPv6 expected';
} else if (type === 'ip4') {
return validateIp4(value);
} else if (type === 'ip6') {
return validateIp6(value);
}
return '';
}
function validateIp4(value) {
const ipElements = value.trim().split('.');
if (ipElements.length !== 4) {
return 'IPv4 expected'
}
for (const element of ipElements) {
if (isEmptyString(element)) {
return 'Empty IP block'
}
if (!/^[12]?[0-9]{1,2}$/.test(element)) {
return 'Invalid block ' + element;
}
const elementNumeric = parseInt(element, 10);
if (elementNumeric > 255) {
return 'Out of range ' + elementNumeric;
}
}
return '';
}
function validateIp6(value) {
const chunks = value.trim().split('::');
if (chunks.length > 2) {
return ':: allowed only once';
}
const elements = [];
elements.push(...chunks[0].split(':'));
if (chunks.length === 2) {
elements.push('::');
elements.push(...chunks[1].split(':'))
}
const hasCompressZeroes = chunks.length === 2;
let afterDoubleColon = false;
let hasIp4 = false;
let count = 0;
for (const element of elements) {
if (hasIp4) {
return 'IPv4 should be the last';
}
if (element === '::') {
afterDoubleColon = true;
} else if (element.includes('.') && ((afterDoubleColon || count >= 6))) {
if (!isEmptyString(validateIp4(element))) {
return 'Invalid IPv4 block ' + element;
}
hasIp4 = true;
count++;
} else if (!/^[A-F0-9]{0,4}$/.test(element.toUpperCase())) {
return 'Invalid block ' + element;
}
count++;
}
if (((count < 8) && (!hasCompressZeroes)) || (count > 8)) {
return 'Should be 8 blocks';
}
return "";
return '';
}
function getInvalidTypeError(type) {
if (type === 'int') {
return "integer expected";
return 'integer expected';
}
return type + " expected";
return type + ' expected';
}
</script>
16 changes: 13 additions & 3 deletions web-src/js/script/script-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ ScriptController.prototype._initStore = function () {
parameterValues: {},
parameterErrors: {},
executing: false,
showLog: false,
downloadableFiles: [],
inputPromptText: null,
sentValues: {},
Expand Down Expand Up @@ -355,9 +356,14 @@ ScriptController.prototype._initStore = function () {
});

controller.scriptView.$nextTick(function () {
var parameterValues = state.parameterValues;
const parameterValues = state.parameterValues;
const parameterErrors = state.parameterErrors;

forEachKeyValue(parameterValues, function (key, value) {
controller._sendCurrentValue(key, value);
const errorMessage = parameterErrors[key];
const valueToSend = isEmptyString(errorMessage) ? value : null;

controller._sendCurrentValue(key, valueToSend);
});
});
},
Expand Down Expand Up @@ -447,6 +453,10 @@ ScriptController.prototype._initStore = function () {

[SET_EXECUTING](state, executing) {
state.executing = executing;

if (executing) {
state.showLog = true;
}
},

[SET_INPUT_PROMPT](state, promptText) {
Expand Down Expand Up @@ -505,7 +515,7 @@ ScriptController.prototype._initStore = function () {
if (!(error instanceof HttpUnauthorizedError)) {
logError(error);

commit.commit(APPEND_LOG_CHUNK, {text: '\n\n' + error.message});
commit(APPEND_LOG_CHUNK, {text: '\n\n' + error.message});
}
}

Expand Down
Loading

0 comments on commit 08fc1b3

Please sign in to comment.