From 818b9d87b8ab1ca2fc4964dcf20e4436b4a446e3 Mon Sep 17 00:00:00 2001 From: Jakob Ketterl Date: Thu, 30 Sep 2021 23:26:26 +0200 Subject: [PATCH] add a validator that prevents invalid locations --- owrx/controllers/settings/general.py | 2 +- owrx/form/input/__init__.py | 40 ----------------- owrx/form/input/location.py | 64 ++++++++++++++++++++++++++++ owrx/form/input/validator.py | 6 +-- 4 files changed, 68 insertions(+), 44 deletions(-) create mode 100644 owrx/form/input/location.py diff --git a/owrx/controllers/settings/general.py b/owrx/controllers/settings/general.py index e12c101..4da68b6 100644 --- a/owrx/controllers/settings/general.py +++ b/owrx/controllers/settings/general.py @@ -5,7 +5,6 @@ from owrx.form.input import ( TextInput, NumberInput, FloatInput, - LocationInput, TextAreaInput, DropdownInput, Option, @@ -14,6 +13,7 @@ from owrx.form.input.converter import WaterfallColorsConverter, IntConverter from owrx.form.input.receiverid import ReceiverKeysConverter from owrx.form.input.gfx import AvatarInput, TopPhotoInput from owrx.form.input.device import WaterfallLevelsInput, WaterfallAutoLevelsInput +from owrx.form.input.location import LocationInput from owrx.waterfall import WaterfallOptions from owrx.breadcrumb import Breadcrumb, BreadcrumbItem from owrx.controllers.settings import SettingsBreadcrumb diff --git a/owrx/form/input/__init__.py b/owrx/form/input/__init__.py index f25279a..5d95b6b 100644 --- a/owrx/form/input/__init__.py +++ b/owrx/form/input/__init__.py @@ -1,6 +1,5 @@ from abc import ABC from owrx.modes import Modes -from owrx.config import Config from owrx.form.input.validator import Validator from owrx.form.input.converter import Converter, NullConverter, IntConverter, FloatConverter, EnumConverter from enum import Enum @@ -158,45 +157,6 @@ class FloatInput(NumberInput): return FloatConverter() -class LocationInput(Input): - def render_input_group(self, value, errors): - return """ -
- {inputs} -
- {errors} -
-
-
- """.format( - id=self.id, - rowclass="is-invalid" if errors else "", - inputs=self.render_input(value, errors), - errors=self.render_errors(errors), - key=Config.get()["google_maps_api_key"], - ) - - def render_input(self, value, errors): - return "".join(self.render_sub_input(value, id, errors) for id in ["lat", "lon"]) - - def render_sub_input(self, value, id, errors): - return """ -
- -
- """.format( - id="{0}-{1}".format(self.id, id), - label=self.label, - classes=self.input_classes(errors), - value=value[id], - disabled="disabled" if self.disabled else "", - ) - - def parse(self, data): - return {self.id: {k: float(data["{0}-{1}".format(self.id, k)][0]) for k in ["lat", "lon"]}} - - class TextAreaInput(Input): def render_input(self, value, errors): return """ diff --git a/owrx/form/input/location.py b/owrx/form/input/location.py new file mode 100644 index 0000000..3a9fcb3 --- /dev/null +++ b/owrx/form/input/location.py @@ -0,0 +1,64 @@ +from owrx.form.input import Input +from owrx.form.input.validator import Validator +from owrx.form.error import ValidationError +from owrx.config import Config + +import logging + +logger = logging.getLogger(__name__) + + +class LocationValidator(Validator): + def validate(self, key, value): + if "lat" in value and not -90 < value["lat"] < 90: + raise ValidationError(key, "Latitude out of range (-90 to 90)") + if "lon" in value and not -180 < value["lon"] < 180: + raise ValidationError(key, "Longitude out of range (-180 to 180)") + pass + + +class LocationInput(Input): + def __init__(self, id, label, validator: Validator = None): + if validator is None: + validator = LocationValidator() + super().__init__(id, label, validator=validator) + + def render_input_group(self, value, errors): + return """ +
+ {inputs} +
+ {errors} +
+
+
+ """.format( + id=self.id, + rowclass="is-invalid" if errors else "", + inputs=self.render_input(value, errors), + errors=self.render_errors(errors), + key=Config.get()["google_maps_api_key"], + ) + + def render_input(self, value, errors): + return "".join(self.render_sub_input(value, id, errors) for id in ["lat", "lon"]) + + def render_sub_input(self, value, id, errors): + return """ +
+ +
+ """.format( + id="{0}-{1}".format(self.id, id), + label=self.label, + classes=self.input_classes(errors), + value=value[id], + disabled="disabled" if self.disabled else "", + ) + + def parse(self, data): + value = {k: float(data["{0}-{1}".format(self.id, k)][0]) for k in ["lat", "lon"]} + if self.validator is not None: + self.validator.validate(self.id, value) + return {self.id: value} diff --git a/owrx/form/input/validator.py b/owrx/form/input/validator.py index 1bf1caa..fe4e16e 100644 --- a/owrx/form/input/validator.py +++ b/owrx/form/input/validator.py @@ -4,12 +4,12 @@ from owrx.form.error import ValidationError class Validator(ABC): @abstractmethod - def validate(self, key, value): + def validate(self, key, value) -> None: pass class RequiredValidator(Validator): - def validate(self, key, value): + def validate(self, key, value) -> None: if value is None or value == "": raise ValidationError(key, "Field is required") @@ -19,7 +19,7 @@ class RangeValidator(Validator): self.minValue = minValue self.maxValue = maxValue - def validate(self, key, value): + def validate(self, key, value) -> None: if value is None or value == "": return # Ignore empty values n = float(value)