From 48ef41da7f0e19ce3654914be21b7ae251fa7ec9 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Mon, 9 Jan 2023 15:42:37 -0800 Subject: [PATCH 01/56] fix use_location bug --- src/django_idom/hooks.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/django_idom/hooks.py b/src/django_idom/hooks.py index 4455f779..b40735c9 100644 --- a/src/django_idom/hooks.py +++ b/src/django_idom/hooks.py @@ -45,7 +45,9 @@ def use_location() -> Location: # TODO: Use the browser's current page, rather than the WS route scope = use_scope() search = scope["query_string"].decode() - return Location(scope["path"], f"?{search}" if search else "") + return Location( + scope["path"], f"?{search}" if (search and (search != "undefined")) else "" + ) def use_origin() -> str | None: From 89a59d6a08b97c56fa865ead8bd0b6fe4170b9ae Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Mon, 9 Jan 2023 16:55:07 -0800 Subject: [PATCH 02/56] add missing migration --- .../0003_alter_relationalparent_one_to_one.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/test_app/migrations/0003_alter_relationalparent_one_to_one.py diff --git a/tests/test_app/migrations/0003_alter_relationalparent_one_to_one.py b/tests/test_app/migrations/0003_alter_relationalparent_one_to_one.py new file mode 100644 index 00000000..1d3ab63d --- /dev/null +++ b/tests/test_app/migrations/0003_alter_relationalparent_one_to_one.py @@ -0,0 +1,24 @@ +# Generated by Django 4.1.3 on 2023-01-10 00:52 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("test_app", "0002_relationalchild_relationalparent_foriegnchild"), + ] + + operations = [ + migrations.AlterField( + model_name="relationalparent", + name="one_to_one", + field=models.OneToOneField( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="one_to_one", + to="test_app.relationalchild", + ), + ), + ] From 2247a183e210841d00bd7679c3556069b6aee3d0 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Mon, 9 Jan 2023 16:55:20 -0800 Subject: [PATCH 03/56] enable django mypy plugin --- pyproject.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 6bf3a9fc..181cbf89 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,3 +17,8 @@ warn_unused_configs = true warn_redundant_casts = true warn_unused_ignores = true check_untyped_defs = true +plugins = ["mypy_django_plugin.main"] + +[tool.django-stubs] +django_settings_module = 'test_app.settings' + From f2b5a3a496df836eb3ac1b577216bc94f797ecd6 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Mon, 9 Jan 2023 18:23:31 -0800 Subject: [PATCH 04/56] Functional DB-backed component params --- CHANGELOG.md | 4 +- requirements/pkg-deps.txt | 1 + src/django_idom/config.py | 6 +-- src/django_idom/migrations/0001_initial.py | 26 ++++++++++ src/django_idom/migrations/__init__.py | 0 src/django_idom/models.py | 7 +++ src/django_idom/templates/idom/component.html | 7 ++- src/django_idom/templatetags/idom.py | 33 ++++++++----- src/django_idom/types.py | 11 ++++- src/django_idom/utils.py | 10 +++- src/django_idom/websocket/consumer.py | 36 +++++++++----- src/django_idom/websocket/paths.py | 2 +- src/js/src/index.js | 49 +++++++++---------- tests/test_app/components.py | 2 +- 14 files changed, 131 insertions(+), 63 deletions(-) create mode 100644 src/django_idom/migrations/0001_initial.py create mode 100644 src/django_idom/migrations/__init__.py create mode 100644 src/django_idom/models.py diff --git a/CHANGELOG.md b/CHANGELOG.md index ce7c1daa..460bfce7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,9 @@ Using the following categories, list your changes in this order: ## [Unreleased] -- Nothing (yet) +### Security + +- Fixed a potential method of component argument spoofing ## [2.2.1] - 2022-01-09 diff --git a/requirements/pkg-deps.txt b/requirements/pkg-deps.txt index d2329eb6..873b689f 100644 --- a/requirements/pkg-deps.txt +++ b/requirements/pkg-deps.txt @@ -1,4 +1,5 @@ channels >=4.0.0 idom >=0.40.2, <0.41.0 aiofile >=3.0 +dill >=0.3.5 typing_extensions diff --git a/src/django_idom/config.py b/src/django_idom/config.py index 0e1d4cd7..7cd8a6db 100644 --- a/src/django_idom/config.py +++ b/src/django_idom/config.py @@ -17,10 +17,10 @@ "IDOM_WEBSOCKET_URL", "idom/", ) -IDOM_WS_MAX_RECONNECT_TIMEOUT = getattr( +IDOM_MAX_RECONNECT_TIMEOUT = getattr( settings, - "IDOM_WS_MAX_RECONNECT_TIMEOUT", - 604800, + "IDOM_MAX_RECONNECT_TIMEOUT", + 259200, # Default to 3 days ) IDOM_CACHE: BaseCache = ( caches["idom"] diff --git a/src/django_idom/migrations/0001_initial.py b/src/django_idom/migrations/0001_initial.py new file mode 100644 index 00000000..3ad19d56 --- /dev/null +++ b/src/django_idom/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 4.1.3 on 2023-01-10 00:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="ComponentParams", + fields=[ + ( + "uuid", + models.UUIDField( + editable=False, primary_key=True, serialize=False, unique=True + ), + ), + ("data", models.BinaryField()), + ("created_at", models.DateTimeField(auto_now_add=True)), + ], + ), + ] diff --git a/src/django_idom/migrations/__init__.py b/src/django_idom/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/django_idom/models.py b/src/django_idom/models.py new file mode 100644 index 00000000..4e509255 --- /dev/null +++ b/src/django_idom/models.py @@ -0,0 +1,7 @@ +from django.db import models + + +class ComponentParams(models.Model): + uuid = models.UUIDField(primary_key=True, editable=False, unique=True) + data = models.BinaryField(editable=False) + created_at = models.DateTimeField(auto_now_add=True, editable=False) diff --git a/src/django_idom/templates/idom/component.html b/src/django_idom/templates/idom/component.html index fc8ba6f8..91f83222 100644 --- a/src/django_idom/templates/idom/component.html +++ b/src/django_idom/templates/idom/component.html @@ -2,13 +2,12 @@
diff --git a/src/django_idom/templatetags/idom.py b/src/django_idom/templatetags/idom.py index b6bb6868..d09aa74a 100644 --- a/src/django_idom/templatetags/idom.py +++ b/src/django_idom/templatetags/idom.py @@ -1,13 +1,13 @@ -import json -from typing import Any -from urllib.parse import urlencode from uuid import uuid4 +import dill as pickle from django import template from django.urls import reverse -from django_idom.config import IDOM_WEBSOCKET_URL, IDOM_WS_MAX_RECONNECT_TIMEOUT -from django_idom.utils import _register_component +from django_idom import models +from django_idom.config import IDOM_MAX_RECONNECT_TIMEOUT, IDOM_WEBSOCKET_URL +from django_idom.types import ComponentParamData +from django_idom.utils import _register_component, func_has_params IDOM_WEB_MODULES_URL = reverse("idom:web_modules", args=["x"])[:-1][1:] @@ -15,11 +15,12 @@ @register.inclusion_tag("idom/component.html") -def component(dotted_path: str, **kwargs: Any): +def component(dotted_path: str, *args, **kwargs): """This tag is used to embed an existing IDOM component into your HTML template. Args: dotted_path: The dotted path to the component to render. + *args: The positional arguments to pass to the component. Keyword Args: **kwargs: The keyword arguments to pass to the component. @@ -34,17 +35,23 @@ def component(dotted_path: str, **kwargs: Any):