Skip to content

Commit

Permalink
update validation, add def class tests (#1456)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Jan 8, 2025
1 parent a812cef commit f7cea3b
Show file tree
Hide file tree
Showing 3 changed files with 334 additions and 29 deletions.
32 changes: 4 additions & 28 deletions projectroles/app_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,6 @@ def get_default(
s_def = s_defs[setting_name]
if callable(s_def.default):
try:
# callable_setting = s_def.default
return s_def.default(project, user)
except Exception:
logger.error(
Expand Down Expand Up @@ -669,7 +668,7 @@ def validate(
"""
Validate setting value according to its type.
:param setting_type: Setting type
:param setting_type: Setting type (string)
:param setting_value: Setting value
:param setting_options: Setting options (can be None)
:param project: Project object (optional)
Expand All @@ -680,34 +679,11 @@ def validate(
cls._validate_value_in_options(
setting_value, setting_options, project=project, user=user
)
# Test callable
# Test callable value
if callable(setting_value):
setting_value(project, user)

if setting_type == APP_SETTING_TYPE_BOOLEAN:
if not isinstance(setting_value, bool):
raise ValueError(
'Please enter a valid boolean value ({})'.format(
setting_value
)
)
elif setting_type == APP_SETTING_TYPE_INTEGER:
if (
not isinstance(setting_value, int)
and not str(setting_value).isdigit()
):
raise ValueError(
'Please enter a valid integer value ({})'.format(
setting_value
)
)
elif setting_type == APP_SETTING_TYPE_JSON:
try:
json.dumps(setting_value)
except TypeError:
raise ValueError(
'Please enter valid JSON ({})'.format(setting_value)
)
else: # Else validate normal value
PluginAppSettingDef.validate_value(setting_type, setting_value)
return True

@classmethod
Expand Down
77 changes: 76 additions & 1 deletion projectroles/plugins.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Plugin point definitions and plugin API for apps based on projectroles"""

import json

from django.conf import settings
from djangoplugins.point import PluginPoint

Expand All @@ -14,7 +16,9 @@
'APP_SETTING_SCOPE_PROJECT_USER'
]
APP_SETTING_SCOPE_SITE = SODAR_CONSTANTS['APP_SETTING_SCOPE_SITE']
APP_SETTING_TYPE_BOOLEAN = SODAR_CONSTANTS['APP_SETTING_TYPE_BOOLEAN']
APP_SETTING_TYPE_INTEGER = SODAR_CONSTANTS['APP_SETTING_TYPE_INTEGER']
APP_SETTING_TYPE_JSON = SODAR_CONSTANTS['APP_SETTING_TYPE_JSON']
APP_SETTING_TYPE_STRING = SODAR_CONSTANTS['APP_SETTING_TYPE_STRING']

# Local constants
Expand Down Expand Up @@ -697,14 +701,24 @@ def __init__(
:parm widget_attrs: Form widget attributes (optional, dict)
:raise: ValueError if an argument is not valid
"""
# Validate provided values
self.validate_scope(scope)
self.validate_type(type)
self.validate_type_options(type, options)
if not callable(default):
self.validate_value(type, default)
if (
default is not None
and options is not None
and not callable(default)
and not callable(options)
):
self.validate_default_in_options(default, options)
# TODO: Prevent using the same name in the same plugin
# Set members
self.name = name
self.scope = scope
self.type = type
# TODO: Validate default against type
self.default = default
self.label = label
self.placeholder = placeholder
Expand Down Expand Up @@ -756,6 +770,67 @@ def validate_type_options(cls, setting_type, setting_options):
'STRING'
)

@classmethod
def validate_default_in_options(cls, setting_default, setting_options):
"""
Validate existence of default value in uncallable options.
:param setting_default: Default value
:param setting_options: Setting options
:raise: ValueError if default is not found in options
"""
if (
setting_options is not None
and not callable(setting_options)
and setting_default is not None
and not callable(setting_default)
and setting_default not in setting_options
):
raise ValueError(
'Default value "{}" not found in options ({})'.format(
setting_default,
', '.join([str(o) for o in setting_options]),
)
)

@classmethod
def validate_value(cls, setting_type, setting_value):
"""
Validate non-callable value.
:param setting_type: Setting type (string)
:param setting_value: Setting value
:raise: ValueError if value is invalid
"""
if setting_type == APP_SETTING_TYPE_BOOLEAN:
if not isinstance(setting_value, bool):
raise ValueError(
'Please enter value as bool ({})'.format(setting_value)
)
elif setting_type == APP_SETTING_TYPE_INTEGER:
if (
not isinstance(setting_value, int)
and not str(setting_value).isdigit()
):
raise ValueError(
'Please enter a valid integer value ({})'.format(
setting_value
)
)
elif setting_type == APP_SETTING_TYPE_JSON:
if setting_value and not isinstance(setting_value, (dict, list)):
raise ValueError(
'Please input JSON value as dict or list ({})'.format(
setting_value
)
)
try:
json.dumps(setting_value)
except TypeError:
raise ValueError(
'Please enter valid JSON ({})'.format(setting_value)
)


class PluginObjectLink:
"""
Expand Down
Loading

0 comments on commit f7cea3b

Please sign in to comment.