From b4d21e7113384bbb592bbd79bca06aeb9e4d640a Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Mon, 21 Aug 2023 07:59:57 +0300 Subject: [PATCH] prevent API options from being changed via API --- modules/api/api.py | 2 +- modules/options.py | 19 +++++++++++++------ modules/shared_options.py | 6 +++--- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/modules/api/api.py b/modules/api/api.py index 42fbbe3da..e6edffe71 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -570,7 +570,7 @@ class Api: raise RuntimeError(f"model {checkpoint_name!r} not found") for k, v in req.items(): - shared.opts.set(k, v) + shared.opts.set(k, v, is_api=True) shared.opts.save(shared.config_filename) return diff --git a/modules/options.py b/modules/options.py index db1fb157e..41d1b672c 100644 --- a/modules/options.py +++ b/modules/options.py @@ -8,7 +8,7 @@ from modules.shared_cmd_options import cmd_opts class OptionInfo: - def __init__(self, default=None, label="", component=None, component_args=None, onchange=None, section=None, refresh=None, comment_before='', comment_after='', infotext=None): + def __init__(self, default=None, label="", component=None, component_args=None, onchange=None, section=None, refresh=None, comment_before='', comment_after='', infotext=None, restrict_api=False): self.default = default self.label = label self.component = component @@ -26,6 +26,9 @@ class OptionInfo: self.infotext = infotext + self.restrict_api = restrict_api + """If True, the setting will not be accessible via API""" + def link(self, label, url): self.comment_before += f"[{label}]" return self @@ -71,7 +74,7 @@ options_builtin_fields = {"data_labels", "data", "restricted_opts", "typemap"} class Options: typemap = {int: float} - def __init__(self, data_labels, restricted_opts): + def __init__(self, data_labels: dict[str, OptionInfo], restricted_opts): self.data_labels = data_labels self.data = {k: v.default for k, v in self.data_labels.items()} self.restricted_opts = restricted_opts @@ -113,14 +116,18 @@ class Options: return super(Options, self).__getattribute__(item) - def set(self, key, value): + def set(self, key, value, is_api=False): """sets an option and calls its onchange callback, returning True if the option changed and False otherwise""" oldval = self.data.get(key, None) if oldval == value: return False - if self.data_labels[key].do_not_save: + option = self.data_labels[key] + if option.do_not_save: + return False + + if is_api and option.restrict_api: return False try: @@ -128,9 +135,9 @@ class Options: except RuntimeError: return False - if self.data_labels[key].onchange is not None: + if option.onchange is not None: try: - self.data_labels[key].onchange() + option.onchange() except Exception as e: errors.display(e, f"changing setting {key} to {value}") setattr(self, key, oldval) diff --git a/modules/shared_options.py b/modules/shared_options.py index 5f30e8e98..6f1a738d6 100644 --- a/modules/shared_options.py +++ b/modules/shared_options.py @@ -112,9 +112,9 @@ options_templates.update(options_section(('system', "System"), { })) options_templates.update(options_section(('API', "API"), { - "api_enable_requests": OptionInfo(True, "Allow http:// and https:// URLs for input images in API"), - "api_forbid_local_requests": OptionInfo(True, "Forbid URLs to local resources"), - "api_useragent": OptionInfo("", "User agent for requests"), + "api_enable_requests": OptionInfo(True, "Allow http:// and https:// URLs for input images in API", restrict_api=True), + "api_forbid_local_requests": OptionInfo(True, "Forbid URLs to local resources", restrict_api=True), + "api_useragent": OptionInfo("", "User agent for requests", restrict_api=True), })) options_templates.update(options_section(('training', "Training"), {