Skip to content

Commit e6dc2ed

Browse files
committed
vue visitors: introduced optional value masking and migration
CMK-24633 Change-Id: I54f1052f5f2afe86a51266ac28d98a2dfc4c2100
1 parent a9574ac commit e6dc2ed

53 files changed

Lines changed: 322 additions & 234 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.werks/18202.md

Lines changed: 0 additions & 33 deletions
This file was deleted.

cmk/gui/form_specs/vue/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
InvalidValue,
1616
RawDiskData,
1717
RawFrontendData,
18+
VisitorOptions,
1819
)
1920
from .form_spec_visitor import (
2021
DisplayMode,
@@ -28,6 +29,7 @@
2829
"get_visitor",
2930
"DEFAULT_VALUE",
3031
"DefaultValue",
32+
"VisitorOptions",
3133
"DiskModel",
3234
"IncomingData",
3335
"InvalidValue",

cmk/gui/form_specs/vue/_registry.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from cmk.ccc.exceptions import MKGeneralException
99
from cmk.rulesets.v1.form_specs import FormSpec
1010

11+
from ._type_defs import VisitorOptions
1112
from ._visitor_base import FormSpecVisitor
1213

1314
RecomposerFunction = Callable[[FormSpec[Any]], FormSpec[Any]]
@@ -29,12 +30,14 @@ def register_recomposer_function(
2930
form_spec_recomposer_registry[form_spec_class] = recomposer_function
3031

3132

32-
def get_visitor(form_spec: FormSpec[Any]) -> FormSpecVisitor[FormSpec[Any], Any, Any]:
33+
def get_visitor(
34+
form_spec: FormSpec[Any], visitor_options: VisitorOptions
35+
) -> FormSpecVisitor[FormSpec[Any], Any, Any]:
3336
if recompose_function := form_spec_recomposer_registry.get(form_spec.__class__):
34-
return get_visitor(recompose_function(form_spec))
37+
return get_visitor(recompose_function(form_spec), visitor_options)
3538

3639
if visitor_class := form_spec_visitor_registry.get(form_spec.__class__):
37-
return visitor_class(form_spec)
40+
return visitor_class(form_spec, visitor_options)
3841

3942
raise MKGeneralException(
4043
f"No visitor found for form spec class: {form_spec.__class__.__name__}"

cmk/gui/form_specs/vue/_type_defs.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,9 @@ def __init__(self, messages: list[ValidationMessage]) -> None:
4646
@property
4747
def messages(self) -> list[ValidationMessage]:
4848
return self._messages
49+
50+
51+
@dataclass(kw_only=True)
52+
class VisitorOptions:
53+
migrate_values: bool
54+
mask_values: bool

cmk/gui/form_specs/vue/_visitor_base.py

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from cmk.rulesets.v1.form_specs import FormSpec
1111
from cmk.shared_typing import vue_formspec_components as shared_type_defs
1212

13-
from ._type_defs import DiskModel, IncomingData, InvalidValue, RawDiskData
13+
from ._type_defs import DiskModel, IncomingData, InvalidValue, RawDiskData, VisitorOptions
1414
from ._utils import (
1515
compute_validation_errors,
1616
compute_validators,
@@ -25,17 +25,26 @@
2525

2626
class FormSpecVisitor(abc.ABC, Generic[FormSpecModel, _ParsedValueModel, _FallbackDataModel]):
2727
@final
28-
def __init__(self, form_spec: FormSpecModel) -> None:
28+
def __init__(self, form_spec: FormSpecModel, visitor_options: VisitorOptions) -> None:
2929
self.form_spec = form_spec
30+
self.visitor_options = visitor_options
3031

3132
@final
3233
def to_vue(self, raw_value: IncomingData) -> tuple[shared_type_defs.FormSpec, object]:
33-
parsed_value = self._parse_value(self._migrate_disk_value(raw_value))
34+
parsed_value = self._parse_value(
35+
self._migrate_disk_value(raw_value)
36+
if self.visitor_options.migrate_values
37+
else raw_value
38+
)
3439
return self._to_vue(parsed_value)
3540

3641
@final
3742
def validate(self, raw_value: IncomingData) -> list[shared_type_defs.ValidationMessage]:
38-
parsed_value = self._parse_value(self._migrate_disk_value(raw_value))
43+
parsed_value = self._parse_value(
44+
self._migrate_disk_value(raw_value)
45+
if self.visitor_options.migrate_values
46+
else raw_value
47+
)
3948
# Stage 1: Check if the value is invalid
4049
if isinstance(parsed_value, InvalidValue):
4150
return create_validation_error(self._to_vue(parsed_value)[1], parsed_value.reason)
@@ -55,22 +64,17 @@ def validate(self, raw_value: IncomingData) -> list[shared_type_defs.ValidationM
5564

5665
@final
5766
def to_disk(self, raw_value: IncomingData) -> DiskModel:
58-
parsed_value = self._parse_value(self._migrate_disk_value(raw_value))
67+
parsed_value = self._parse_value(
68+
self._migrate_disk_value(raw_value)
69+
if self.visitor_options.migrate_values
70+
else raw_value
71+
)
5972
if isinstance(parsed_value, InvalidValue):
6073
raise MKGeneralException(
6174
"Unable to serialize invalid value. Reason: %s" % parsed_value.reason
6275
)
6376
return self._to_disk(parsed_value)
6477

65-
@final
66-
def mask(self, raw_value: IncomingData) -> DiskModel:
67-
parsed_value = self._parse_value(self._migrate_disk_value(raw_value))
68-
if isinstance(parsed_value, InvalidValue):
69-
raise MKGeneralException(
70-
"Unable to serialize invalid value. Reason: %s" % parsed_value.reason
71-
)
72-
return self._mask(parsed_value)
73-
7478
def _migrate_disk_value(self, value: IncomingData) -> IncomingData:
7579
if isinstance(value, RawDiskData) and self.form_spec.migrate:
7680
return RawDiskData(value=self.form_spec.migrate(value.value))
@@ -103,11 +107,3 @@ def _validate(
103107
@abc.abstractmethod
104108
def _to_disk(self, parsed_value: _ParsedValueModel) -> DiskModel:
105109
"""Transforms the value into a serializable format for disk storage."""
106-
107-
def _mask(self, parsed_value: _ParsedValueModel) -> DiskModel:
108-
"""Obscure any sensitive information in the provided value
109-
110-
Container-like ValueSpecs must recurse over their items, allow these to mask their
111-
values. Other ValueSpecs that don't have a need for masking sensitive information
112-
can simply return the input value."""
113-
return self._to_disk(parsed_value)

cmk/gui/form_specs/vue/form_spec_visitor.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@
2121
from cmk.shared_typing import vue_formspec_components as shared_type_defs
2222

2323
from ._registry import get_visitor
24-
from ._type_defs import DEFAULT_VALUE, FormSpecValidationError, IncomingData, RawFrontendData
24+
from ._type_defs import (
25+
DEFAULT_VALUE,
26+
FormSpecValidationError,
27+
IncomingData,
28+
RawFrontendData,
29+
VisitorOptions,
30+
)
2531

2632
T = TypeVar("T")
2733

@@ -100,15 +106,15 @@ def parse_data_from_frontend(form_spec: FormSpec[T], field_id: str) -> object:
100106
if not request.has_var(field_id):
101107
raise MKGeneralException("Formular data is missing in request")
102108
value_from_frontend = RawFrontendData(json.loads(request.get_str_input_mandatory(field_id)))
103-
visitor = get_visitor(form_spec)
109+
visitor = get_visitor(form_spec, VisitorOptions(migrate_values=False, mask_values=False))
104110
_process_validation_errors(visitor.validate(value_from_frontend))
105111
return visitor.to_disk(value_from_frontend)
106112

107113

108114
def validate_value_from_frontend(
109115
form_spec: FormSpec[T], value: IncomingData
110116
) -> Sequence[shared_type_defs.ValidationMessage]:
111-
visitor = get_visitor(form_spec)
117+
visitor = get_visitor(form_spec, VisitorOptions(migrate_values=True, mask_values=False))
112118
return visitor.validate(value)
113119

114120

@@ -120,7 +126,7 @@ def serialize_data_for_frontend(
120126
display_mode: DisplayMode = DisplayMode.EDIT,
121127
) -> VueAppConfig:
122128
"""Serializes backend value to vue app compatible config."""
123-
visitor = get_visitor(form_spec)
129+
visitor = get_visitor(form_spec, VisitorOptions(migrate_values=True, mask_values=False))
124130
vue_component, vue_value = visitor.to_vue(value)
125131

126132
validation: list[shared_type_defs.ValidationMessage] = []

cmk/gui/form_specs/vue/visitors/cascading_single_choice.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def _to_vue(
7676
selected_vue_value: object = None
7777
vue_elements = []
7878
for element in self.form_spec.elements:
79-
element_visitor = get_visitor(element.parameter_form)
79+
element_visitor = get_visitor(element.parameter_form, self.visitor_options)
8080
element_value = selected_value if selected_name == element.name else DEFAULT_VALUE
8181
element_schema, element_vue_value = element_visitor.to_vue(element_value)
8282

@@ -117,7 +117,7 @@ def _validate(
117117
if selected_name != element.name:
118118
continue
119119

120-
element_visitor = get_visitor(element.parameter_form)
120+
element_visitor = get_visitor(element.parameter_form, self.visitor_options)
121121
for validation in element_visitor.validate(selected_value):
122122
element_validations.append(
123123
shared_type_defs.ValidationMessage(
@@ -137,6 +137,6 @@ def _to_disk(self, parsed_value: _ParsedValueModel) -> tuple[str, object]:
137137
for element in self.form_spec.elements:
138138
if selected_name != element.name:
139139
continue
140-
element_visitor = get_visitor(element.parameter_form)
140+
element_visitor = get_visitor(element.parameter_form, self.visitor_options)
141141
disk_value = element_visitor.to_disk(selected_value)
142142
return selected_name, disk_value

cmk/gui/form_specs/vue/visitors/catalog.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def _to_vue(
149149

150150
element_lookup: dict[str, tuple[shared_type_defs.FormSpec, object]] = {}
151151
for element_name, element in actual_elements.items():
152-
element_visitor = get_visitor(element.parameter_form)
152+
element_visitor = get_visitor(element.parameter_form, self.visitor_options)
153153
is_active = element_name in topic_values
154154
spec, value = element_visitor.to_vue(
155155
topic_values[element_name] if is_active else DEFAULT_VALUE
@@ -193,7 +193,7 @@ def _validate(
193193
for topic_name, topic in self.form_spec.elements.items():
194194
topic_values = parsed_value[topic_name]
195195
for element_name, element in self._resolve_topic_to_elements(topic).items():
196-
element_visitor = get_visitor(element.parameter_form)
196+
element_visitor = get_visitor(element.parameter_form, self.visitor_options)
197197
if element_name not in topic_values:
198198
if element.required:
199199
_spec, element_default_value = element_visitor.to_vue(DEFAULT_VALUE)
@@ -222,7 +222,7 @@ def _to_disk(self, parsed_value: _ParsedValueModel) -> Mapping[str, dict[str, ob
222222
topic_values = parsed_value[topic_name]
223223
for element_name, element in self._resolve_topic_to_elements(topic).items():
224224
if element_name in topic_values:
225-
element_visitor = get_visitor(element.parameter_form)
225+
element_visitor = get_visitor(element.parameter_form, self.visitor_options)
226226
disk_values[topic_name][element_name] = element_visitor.to_disk(
227227
topic_values[element_name]
228228
)

cmk/gui/form_specs/vue/visitors/dictionary.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def _to_vue(
117117
vue_values = {}
118118

119119
for key_name, dict_element in self.form_spec.elements.items():
120-
element_visitor = get_visitor(dict_element.parameter_form)
120+
element_visitor = get_visitor(dict_element.parameter_form, self.visitor_options)
121121
is_active = key_name in parsed_value
122122
element_value = parsed_value[key_name] if is_active else DEFAULT_VALUE
123123
element_schema, element_vue_value = element_visitor.to_vue(element_value)
@@ -172,7 +172,7 @@ def _validate(
172172
# NOTE: the parsed_value may include keys with default values, e.g. {"ce": default_value}
173173
element_validations = []
174174
for key_name, dict_element in self.form_spec.elements.items():
175-
element_visitor = get_visitor(dict_element.parameter_form)
175+
element_visitor = get_visitor(dict_element.parameter_form, self.visitor_options)
176176

177177
if key_name not in parsed_value:
178178
if dict_element.required:
@@ -200,7 +200,7 @@ def _validate(
200200
def _to_disk(self, parsed_value: _ParsedValueModel) -> dict[str, object]:
201201
disk_values = {}
202202
for key_name, dict_element in self.form_spec.elements.items():
203-
element_visitor = get_visitor(dict_element.parameter_form)
203+
element_visitor = get_visitor(dict_element.parameter_form, self.visitor_options)
204204
is_active = key_name in parsed_value
205205
if is_active:
206206
disk_values[key_name] = element_visitor.to_disk(parsed_value[key_name])

cmk/gui/form_specs/vue/visitors/list.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def _to_vue(
5757

5858
title, help_text = get_title_and_help(self.form_spec)
5959

60-
element_visitor = get_visitor(self.form_spec.element_template)
60+
element_visitor = get_visitor(self.form_spec.element_template, self.visitor_options)
6161
element_schema, element_vue_default_value = element_visitor.to_vue(DEFAULT_VALUE)
6262
list_values: list[object] = []
6363
for entry in parsed_value:
@@ -93,7 +93,7 @@ def _validate(
9393
self, parsed_value: _ParsedValueModel
9494
) -> list[shared_type_defs.ValidationMessage]:
9595
element_validations: list[shared_type_defs.ValidationMessage] = []
96-
element_visitor = get_visitor(self.form_spec.element_template)
96+
element_visitor = get_visitor(self.form_spec.element_template, self.visitor_options)
9797
for idx, entry in enumerate(parsed_value):
9898
for validation in element_visitor.validate(entry):
9999
element_validations.append(
@@ -108,7 +108,7 @@ def _validate(
108108
@override
109109
def _to_disk(self, parsed_value: _ParsedValueModel) -> list[object]:
110110
disk_values = []
111-
element_visitor = get_visitor(self.form_spec.element_template)
111+
element_visitor = get_visitor(self.form_spec.element_template, self.visitor_options)
112112
for entry in parsed_value:
113113
disk_values.append(element_visitor.to_disk(entry))
114114
return disk_values

0 commit comments

Comments
 (0)