Skip to content

Commit 92e692d

Browse files
Merge pull request #894 from pfrest/next_patch
v2.7.7 Fixes
2 parents 605082c + 19f3292 commit 92e692d

18 files changed

Lines changed: 373 additions & 68 deletions

pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Core/Field.inc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ class Field {
2626
*/
2727
const SENSITIVE_MASK = '********';
2828

29+
/**
30+
* @const MANY_MAXIMUM is the maximum number of items a 'many' field can hold it's array.
31+
*/
32+
const MANY_MAXIMUM = 65535;
33+
2934
/**
3035
* Represents the current value for this Field.
3136
*
@@ -144,7 +149,7 @@ class Field {
144149
public bool $representation_only = false,
145150
public bool $many = false,
146151
public int $many_minimum = 0,
147-
public int $many_maximum = 128,
152+
public int $many_maximum = Field::MANY_MAXIMUM,
148153
public string|null $delimiter = ',',
149154
public string $verbose_name = '',
150155
public string $verbose_name_plural = '',

pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/Base64Field.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class Base64Field extends Field {
8585
bool $representation_only = false,
8686
bool $many = false,
8787
int $many_minimum = 0,
88-
int $many_maximum = 128,
88+
int $many_maximum = Field::MANY_MAXIMUM,
8989
string|null $delimiter = ',',
9090
string $verbose_name = '',
9191
string $verbose_name_plural = '',

pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/DateTimeField.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class DateTimeField extends Field {
9393
bool $representation_only = false,
9494
bool $many = false,
9595
int $many_minimum = 0,
96-
int $many_maximum = 128,
96+
int $many_maximum = Field::MANY_MAXIMUM,
9797
string|null $delimiter = ',',
9898
string $verbose_name = '',
9999
string $verbose_name_plural = '',

pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FilterAddressField.inc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace RESTAPI\Fields;
55
require_once 'RESTAPI/autoloader.inc';
66
require_once 'RESTAPI/Fields/InterfaceField.inc';
77

8+
use RESTAPI\Core\Field;
89
use RESTAPI\Models\FirewallAlias;
910
use RESTAPI\Responses\ServerError;
1011
use RESTAPI\Responses\ValidationError;
@@ -111,7 +112,7 @@ class FilterAddressField extends InterfaceField {
111112
bool $representation_only = false,
112113
bool $many = false,
113114
int $many_minimum = 0,
114-
int $many_maximum = 128,
115+
int $many_maximum = Field::MANY_MAXIMUM,
115116
string|null $delimiter = ',',
116117
string $verbose_name = '',
117118
string $verbose_name_plural = '',

pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ namespace RESTAPI\Fields;
55
require_once 'RESTAPI/autoloader.inc';
66

77
use RESTAPI;
8+
use RESTAPI\Core\Field;
89

910
/**
1011
* Defines a Field object for validating and storing a floating point number.
1112
*/
12-
class FloatField extends RESTAPI\Core\Field {
13+
class FloatField extends Field {
1314
/**
1415
* Defines the FloatField object and sets its options.
1516
* @param bool $required If `true`, this field is required to have a value at all times.
@@ -80,7 +81,7 @@ class FloatField extends RESTAPI\Core\Field {
8081
bool $representation_only = false,
8182
bool $many = false,
8283
int $many_minimum = 0,
83-
int $many_maximum = 128,
84+
int $many_maximum = Field::MANY_MAXIMUM,
8485
public int $minimum = 0,
8586
public int $maximum = PHP_INT_MAX,
8687
string|null $delimiter = ',',

pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/ForeignModelField.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class ForeignModelField extends Field {
118118
bool $representation_only = false,
119119
bool $many = false,
120120
int $many_minimum = 0,
121-
int $many_maximum = 128,
121+
int $many_maximum = Field::MANY_MAXIMUM,
122122
string|null $delimiter = ',',
123123
string $verbose_name = '',
124124
string $verbose_name_plural = '',

pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/IntegerField.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class IntegerField extends Field {
8181
bool $representation_only = false,
8282
bool $many = false,
8383
int $many_minimum = 0,
84-
int $many_maximum = 128,
84+
int $many_maximum = Field::MANY_MAXIMUM,
8585
public int $minimum = 0,
8686
public int $maximum = PHP_INT_MAX,
8787
string|null $delimiter = ',',

pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/InterfaceField.inc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require_once 'RESTAPI/Fields/StringField.inc';
66
require_once 'RESTAPI/autoloader.inc';
77

88
use RESTAPI;
9+
use RESTAPI\Core\Field;
910
use RESTAPI\Core\Model;
1011
use RESTAPI\Core\ModelSet;
1112
use RESTAPI\Models\NetworkInterface;
@@ -97,7 +98,7 @@ class InterfaceField extends StringField {
9798
bool $editable = true,
9899
bool $many = false,
99100
int $many_minimum = 0,
100-
int $many_maximum = 128,
101+
int $many_maximum = Field::MANY_MAXIMUM,
101102
string|null $delimiter = ',',
102103
string $verbose_name = '',
103104
string $verbose_name_plural = '',
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
<?php
2+
3+
namespace RESTAPI\Fields;
4+
5+
require_once 'RESTAPI/autoloader.inc';
6+
7+
use RESTAPI;
8+
use RESTAPI\Core\Field;
9+
10+
/**
11+
* Defines a Field object for validating and storing key length values in the pfSense configuration. This is namely
12+
* for IPsec Phase 2 entries to handle the 'auto' keyword as an integer.
13+
*/
14+
class KeyLenField extends Field {
15+
/**
16+
* Defines the KeyLenField object and sets its options.
17+
* @param bool $required If `true`, this field is required to have a value at all times.
18+
* @param bool $unique If `true`, this field must be unique from all other parent model objects. Enabling this
19+
* option requires the Model $context to be set AND the Model $context must have a `config_path` set.
20+
* @param mixed|null $default Assign a default string value to assign this Field if no value is present.
21+
* @param string $default_callable Defines a callable method that should be called to populate the default value
22+
* for this field. It is strongly encouraged to use a default callable when the default is variable and may change
23+
* dynamically.
24+
* @param array $choices An array of value choices this Field can be assigned. This can either be an indexed array
25+
* of the exact choice values, or an associative array where the array key is the exact choice value and the array
26+
* value is a verbose name for the choice. Verbose choice name are used by ModelForms when generating web pages
27+
* for a given Model.
28+
* @param string $choices_callable Assign a callable method from this Field object OR the parent Model context to
29+
* execute to populate choices for this field. This callable must be a method assigned on this Field object OR the
30+
* parent Model object that returns an array of valid choices in the same format as $choices. This is helpful when
31+
* choices are dynamic and must be populate at runtime instead of pre-determined sets of values.
32+
* @param bool $allow_null If `true`, null values will be allowed by this field.
33+
* @param bool $editable Set to `false` to prevent this field's value from being changed after its initial creation.
34+
* @param bool $read_only If `true`, this field can only read its value and cannot write its value to config.
35+
* @param bool $write_only Set to `true` to make this field write-only. This will prevent the field's current value
36+
* from being displayed in the representation data. This is ideal for potentially sensitive Fields like passwords,
37+
* keys, and hashes.
38+
* @param bool $representation_only Set to `true` to make this field only present in its representation form. This
39+
* effectively prevents the Field from being converted to an internal value which is saved to the pfSense config.
40+
* This should only be used for Fields that do not relate directly to a configuration value.
41+
* @param bool $many If `true`, the value must be an array of many strings.
42+
* @param int $many_minimum When $many is set to `true`, this sets the minimum number of array entries required.
43+
* @param int $many_maximum When $many is set to `true`, this sets the maximum number of array entries allowed.
44+
* @param int $minimum The minimum value this value can be.
45+
* @param int $maximum The maximum value this value can be.
46+
* @param string|null $delimiter Assigns the string delimiter to use when writing array values to config.
47+
* Use `null` if this field is stored as an actual array in config. This is only available if $many is set to
48+
* `true`. Defaults to `,` to store as comma-separated string.
49+
* @param string $verbose_name The detailed name for this Field. This name will be used in non-programmatic areas
50+
* like web pages and help text. This Field will default to property name assigned to the parent Model with
51+
* underscores converted to spaces.
52+
* @param string $verbose_name_plural The plural form of $verbose_name. This defaults to $verbose_name with `s`
53+
* suffixed or `es` suffixes to strings already ending with `s`.
54+
* @param string $internal_name Assign a different field name to use when referring to the internal field as it's
55+
* stored in the pfSense configuration.
56+
* @param string $internal_namespace Sets the namespace this field belongs to internally. This can be used to nest
57+
* the Fields internal value under a specific namespace as an associative array. This only applies to the internal
58+
* value, not the representation value.
59+
* @param array $referenced_by An array that specifies other Models and Field's that reference this Field's parent
60+
* Model using this Field's value. This will prevent the parent Model object from being deleted while it is actively
61+
* referenced by another Model object. The array key must be the name of the Model class that references this Field,
62+
* and the value must be a Field within that Model. The framework will automatically search for any existing Model
63+
* objects that have the referenced Field assigned a value that matches this Field's value.
64+
* @param array $conditions An array of conditions the field must meet to be included. This allows you to specify
65+
* conditions of other Fields within the parent Model context. For example, if the parent Model context has two
66+
* Fields, one field named `type` and the other being this field; and you only want this field to be included if
67+
* `type` is equal to `type1`, you could assign ["type" => "type1"] to this parameter.
68+
* @param array $validators An array of Validator objects to run against this field.
69+
* @param string $help_text Set a description for this field. This description will be used in API documentation.
70+
*/
71+
public function __construct(
72+
bool $required = false,
73+
bool $unique = false,
74+
mixed $default = null,
75+
string $default_callable = '',
76+
array $choices = [],
77+
string $choices_callable = '',
78+
bool $allow_null = false,
79+
bool $editable = true,
80+
bool $read_only = false,
81+
bool $write_only = false,
82+
bool $representation_only = false,
83+
bool $many = false,
84+
int $many_minimum = 0,
85+
int $many_maximum = Field::MANY_MAXIMUM,
86+
public int $minimum = 0,
87+
public int $maximum = PHP_INT_MAX,
88+
string|null $delimiter = ',',
89+
string $verbose_name = '',
90+
string $verbose_name_plural = '',
91+
string $internal_name = '',
92+
string $internal_namespace = '',
93+
array $referenced_by = [],
94+
array $conditions = [],
95+
array $validators = [],
96+
string $help_text = '',
97+
) {
98+
parent::__construct(
99+
type: 'integer',
100+
required: $required,
101+
unique: $unique,
102+
default: $default,
103+
default_callable: $default_callable,
104+
choices: $choices,
105+
choices_callable: $choices_callable,
106+
allow_null: $allow_null,
107+
editable: $editable,
108+
read_only: $read_only,
109+
write_only: $write_only,
110+
representation_only: $representation_only,
111+
many: $many,
112+
many_minimum: $many_minimum,
113+
many_maximum: $many_maximum,
114+
delimiter: $delimiter,
115+
verbose_name: $verbose_name,
116+
verbose_name_plural: $verbose_name_plural,
117+
internal_name: $internal_name,
118+
internal_namespace: $internal_namespace,
119+
referenced_by: $referenced_by,
120+
conditions: $conditions,
121+
validators: $validators + [
122+
new RESTAPI\Validators\NumericRangeValidator(minimum: $minimum, maximum: $maximum),
123+
],
124+
help_text: $help_text,
125+
);
126+
}
127+
128+
/**
129+
* Converts the field value from its representation value into it's internal value. This namely handles converting
130+
* 0 to 'auto'.
131+
* @param mixed $representation_value The representation value to convert to its internal value
132+
*/
133+
protected function _to_internal(mixed $representation_value): array|string|null {
134+
if ($representation_value === 0) {
135+
return parent::_to_internal('auto');
136+
}
137+
return parent::_to_internal($representation_value);
138+
}
139+
140+
/**
141+
* Converts the field value to its representation form from its internal pfSense configuration value.
142+
* @param string $internal_value The internal value from the pfSense configuration.
143+
* @return int The field value in its representation form.
144+
*/
145+
protected function _from_internal(mixed $internal_value): mixed {
146+
# Return the value as an integer if it's numeric
147+
if (is_numeric($internal_value)) {
148+
return intval($internal_value);
149+
}
150+
151+
# If the value is 'auto', return 0 (0 is the representation we use for auto)
152+
if ($internal_value === 'auto') {
153+
return 0;
154+
}
155+
156+
# If the value is an empty string, assume it's null
157+
if ($internal_value === '') {
158+
return null;
159+
}
160+
161+
# Otherwise, the internal value cannot be represented by this Field. Throw an error.
162+
throw new RESTAPI\Responses\ServerError(
163+
message: "Cannot parse KeyLenField '$this->name' from internal because its internal value is not a " .
164+
"numeric value or 'auto'. Consider changing this field to a StringField.",
165+
response_id: 'KEYLEN_FIELD_WITH_NON_INTEGER_INTERNAL_VALUE',
166+
);
167+
}
168+
169+
/**
170+
* Converts this Field object to a PHP array representation of an OpenAPI schema property configuration. This is
171+
* used when auto-generating API documentation. This method can be extended to add additional options to the OpenAPI
172+
* schema property.
173+
* @link https://swagger.io/docs/specification/data-models/
174+
* @return array A PHP array containing this field as a OpenAPI schema property configuration.
175+
*/
176+
public function to_openapi_property(): array {
177+
# Run the parent to_openapi_property() to obtain the base property object, then make changes as needed.
178+
$openapi_property = parent::to_openapi_property();
179+
180+
# Add the minimum and maximum to the OpenAPI property.
181+
if ($this->many) {
182+
$openapi_property['items']['minimum'] = $this->minimum;
183+
$openapi_property['items']['maximum'] = $this->maximum;
184+
} else {
185+
$openapi_property['minimum'] = $this->minimum;
186+
$openapi_property['maximum'] = $this->maximum;
187+
}
188+
189+
return $openapi_property;
190+
}
191+
192+
/**
193+
* Converts this Field object into a pfSense webConfigurator form input. This method can be overridden by a child
194+
* class to add custom input field creation.
195+
* @param string $type The HTML input tag type. Not all Fields support input types.
196+
* @param array $attributes An array of additional HTML input tag attributes. Not all Fields support input attributes.
197+
* @return object The pfSense webConfigurator form input object.
198+
* @link https://github.com/pfsense/pfsense/tree/master/src/usr/local/www/classes/Form
199+
*/
200+
public function to_form_input(string $type = 'number', array $attributes = []): object {
201+
$attributes += ['min' => $this->minimum, 'max' => $this->maximum];
202+
return parent::to_form_input(type: $type, attributes: $attributes);
203+
}
204+
}

pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/ObjectField.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class ObjectField extends Field {
9090
bool $representation_only = false,
9191
bool $many = false,
9292
int $many_minimum = 0,
93-
int $many_maximum = 128,
93+
int $many_maximum = Field::MANY_MAXIMUM,
9494
public int $minimum_length = 0,
9595
public int $maximum_length = 1024,
9696
string|null $delimiter = ',',

0 commit comments

Comments
 (0)