From d378ab28bfeabc9d8a7e8e2440576129e6d3e88b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20H=C3=B6ning?= Date: Mon, 9 Nov 2026 15:58:44 +0100 Subject: [PATCH 1/7] ui/tests: cover child asset creation permissions --- flexmeasures/ui/tests/test_asset_crud.py | 27 +++++++++++++++++------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/flexmeasures/ui/tests/test_asset_crud.py b/flexmeasures/ui/tests/test_asset_crud.py index 14d7915908..19231f637b 100644 --- a/flexmeasures/ui/tests/test_asset_crud.py +++ b/flexmeasures/ui/tests/test_asset_crud.py @@ -675,9 +675,9 @@ def test_breadcrumb_cross_account_parent( # - GenericAsset.create-children (child assets/sensors) → any organisation member # - Account.create-children (top-level assets) → organisation-admin or consultant # -# "user_can_create_assets" (Account.create-children) gates: -# • The "Create asset" child-asset button on the properties page -# • The "Copy this asset" / "Copy to " copy buttons +# "user_can_create_children" (GenericAsset.create-children) gates the +# "Create asset" child-asset button on the properties page. +# The copy buttons have separate permission checks for their target locations. # "user_can_update_asset" (GenericAsset.update) gates the "Edit asset" sidepanel. # "user_can_delete_asset" (GenericAsset.edit-assets, plus delete-data if the asset holds data) gates the "Delete this asset" button. # --------------------------------------------------------------------------- @@ -806,11 +806,11 @@ def test_edit_panel_visibility_on_properties_page( ("as_admin", True, True), # Account-admin of same account: same rights. ("as_prosumer_account_admin", True, True), - # Plain account member: cannot delete an asset holding data or create top-level assets. - ("as_prosumer_user1", False, False), + # Plain account member: cannot delete an asset holding data, but may add children. + ("as_prosumer_user1", False, True), ], ) -def test_admin_only_buttons_on_properties_page( +def test_delete_and_create_buttons_on_properties_page( db, client, setup_assets, @@ -820,8 +820,8 @@ def test_admin_only_buttons_on_properties_page( expect_create_asset_btn, ): """ - 'Delete this asset' and 'Create asset' (child asset via account) are - gated on account-admin permissions and must not appear for plain users. + Deleting an asset holding data needs elevated rights, while creating + a child asset is allowed for any member of the owning organisation. """ from flexmeasures.data.services.users import find_user_by_email @@ -848,6 +848,17 @@ def test_admin_only_buttons_on_properties_page( assert b"Create asset" not in page.data +def test_consultant_can_create_child_asset_from_properties_page( + client, setup_generic_assets, as_consultant +): + parent = setup_generic_assets["test_consultancy_client_asset"] + + page = client.get(url_for("AssetCrudUI:properties", id=parent.id)) + + assert page.status_code == 200 + assert f"/assets/new?parent_asset_id={parent.id}".encode() in page.data + + @pytest.mark.parametrize( "login_fixture, expect_data_query", [ From fdacb80de5b4d7f92dd25fbab69d05712a7fc15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20H=C3=B6ning?= Date: Mon, 9 Nov 2026 15:59:13 +0100 Subject: [PATCH 2/7] ui: show child asset action when parent permits creation --- flexmeasures/ui/templates/assets/asset_properties.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flexmeasures/ui/templates/assets/asset_properties.html b/flexmeasures/ui/templates/assets/asset_properties.html index b0702192f1..4c2e621634 100644 --- a/flexmeasures/ui/templates/assets/asset_properties.html +++ b/flexmeasures/ui/templates/assets/asset_properties.html @@ -241,7 +241,7 @@

All sensors for {{ asset.name }}

All child assets for {{ asset.name }}

- {% if user_can_create_assets %} + {% if user_can_create_children %} Create asset From dea32a123e4fd7d42b31f0df26ea8d30c9d7035a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20H=C3=B6ning?= Date: Mon, 9 Nov 2026 15:59:42 +0100 Subject: [PATCH 3/7] docs: note child asset action permission fix --- documentation/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/documentation/changelog.rst b/documentation/changelog.rst index b51fcfe824..4bf634bb92 100644 --- a/documentation/changelog.rst +++ b/documentation/changelog.rst @@ -18,6 +18,8 @@ Infrastructure / Support Bugfixes ----------- +* Show the child asset creation button to consultants and organisation members who may add assets under a client or organisation asset + * Apply storage losses to the starting stock of a state of charge shared by several devices, so its scheduled state of charge no longer drifts above the one the scheduler planned with [see `PR #2838 `_] * Hovering anywhere over a session in the Charge Points chart shows its tooltip again, listing all of the session's timestamps, as it did before the move to ECharts, without highlighting another charger's session; also, a chart's tooltip no longer shows a point from a neighbouring subplot [see `PR #2829 `_] From d57bf99068a44e316dff7642a3fa04b0e5af49d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20H=C3=B6ning?= Date: Mon, 9 Nov 2026 16:44:11 +0100 Subject: [PATCH 4/7] add changelog entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicolas Höning --- documentation/changelog.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/documentation/changelog.rst b/documentation/changelog.rst index 4bf634bb92..b5309e89ee 100644 --- a/documentation/changelog.rst +++ b/documentation/changelog.rst @@ -18,10 +18,8 @@ Infrastructure / Support Bugfixes ----------- -* Show the child asset creation button to consultants and organisation members who may add assets under a client or organisation asset - +* Show the child asset creation button to consultants and organisation members who may add assets under a client or organisation asset [see `PR #2851 `_] * Apply storage losses to the starting stock of a state of charge shared by several devices, so its scheduled state of charge no longer drifts above the one the scheduler planned with [see `PR #2838 `_] - * Hovering anywhere over a session in the Charge Points chart shows its tooltip again, listing all of the session's timestamps, as it did before the move to ECharts, without highlighting another charger's session; also, a chart's tooltip no longer shows a point from a neighbouring subplot [see `PR #2829 `_] From 75cae186d8ede37d483fcd263c24b841cf9281a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20H=C3=B6ning?= Date: Mon, 9 Nov 2026 22:07:20 +0100 Subject: [PATCH 5/7] ui/tests: match child asset button to UI creation rights --- flexmeasures/ui/tests/test_asset_crud.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/flexmeasures/ui/tests/test_asset_crud.py b/flexmeasures/ui/tests/test_asset_crud.py index 19231f637b..769f944826 100644 --- a/flexmeasures/ui/tests/test_asset_crud.py +++ b/flexmeasures/ui/tests/test_asset_crud.py @@ -675,7 +675,7 @@ def test_breadcrumb_cross_account_parent( # - GenericAsset.create-children (child assets/sensors) → any organisation member # - Account.create-children (top-level assets) → organisation-admin or consultant # -# "user_can_create_children" (GenericAsset.create-children) gates the +# "user_can_create_assets" (Account.edit-assets) gates the # "Create asset" child-asset button on the properties page. # The copy buttons have separate permission checks for their target locations. # "user_can_update_asset" (GenericAsset.update) gates the "Edit asset" sidepanel. @@ -759,6 +759,7 @@ def test_copy_to_own_account_button_for_cross_account_admin( assert page.status_code == 200 assert b"Copy to Test Dummy Account" in page.data assert b"Copy this asset" not in page.data + assert b"Create asset" not in page.data @pytest.mark.parametrize( @@ -806,8 +807,8 @@ def test_edit_panel_visibility_on_properties_page( ("as_admin", True, True), # Account-admin of same account: same rights. ("as_prosumer_account_admin", True, True), - # Plain account member: cannot delete an asset holding data, but may add children. - ("as_prosumer_user1", False, True), + # Plain account member: cannot delete an asset holding data or use the UI to add children. + ("as_prosumer_user1", False, False), ], ) def test_delete_and_create_buttons_on_properties_page( @@ -820,8 +821,8 @@ def test_delete_and_create_buttons_on_properties_page( expect_create_asset_btn, ): """ - Deleting an asset holding data needs elevated rights, while creating - a child asset is allowed for any member of the owning organisation. + Deleting an asset holding data and creating a child asset through the UI + both require elevated rights. """ from flexmeasures.data.services.users import find_user_by_email From 457ca93378ca92336b1f19723d3752706198f317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20H=C3=B6ning?= Date: Mon, 9 Nov 2026 22:07:49 +0100 Subject: [PATCH 6/7] ui: gate child asset action on owner creation rights --- flexmeasures/ui/templates/assets/asset_properties.html | 2 +- flexmeasures/ui/views/assets/views.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/flexmeasures/ui/templates/assets/asset_properties.html b/flexmeasures/ui/templates/assets/asset_properties.html index 4c2e621634..b0702192f1 100644 --- a/flexmeasures/ui/templates/assets/asset_properties.html +++ b/flexmeasures/ui/templates/assets/asset_properties.html @@ -241,7 +241,7 @@

All sensors for {{ asset.name }}

All child assets for {{ asset.name }}

- {% if user_can_create_children %} + {% if user_can_create_assets %}
Create asset diff --git a/flexmeasures/ui/views/assets/views.py b/flexmeasures/ui/views/assets/views.py index ec61452bf4..db509b3206 100644 --- a/flexmeasures/ui/views/assets/views.py +++ b/flexmeasures/ui/views/assets/views.py @@ -513,7 +513,11 @@ def properties(self, id: str): _own_account.id if _can_copy_to_own_account else None ), own_organisation_name=_own_account.name, - user_can_create_assets=user_can_create_assets(), + user_can_create_assets=( + user_can_create_assets(account=asset.owner) + if asset.owner is not None + else current_user.has_role("admin") + ), user_can_create_children=user_can_create_children(asset), user_can_delete_asset=user_can_delete(asset), user_can_update_asset=user_can_update(asset), From f8e0f4628ecb0eef428414ad91cf329b96122e33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20H=C3=B6ning?= Date: Mon, 9 Nov 2026 22:08:18 +0100 Subject: [PATCH 7/7] docs: clarify consultant child asset UI fix --- documentation/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/changelog.rst b/documentation/changelog.rst index b5309e89ee..9198b2e121 100644 --- a/documentation/changelog.rst +++ b/documentation/changelog.rst @@ -18,7 +18,7 @@ Infrastructure / Support Bugfixes ----------- -* Show the child asset creation button to consultants and organisation members who may add assets under a client or organisation asset [see `PR #2851 `_] +* Show the child asset creation button to consultants working on a client organisation's assets [see `PR #2851 `_] * Apply storage losses to the starting stock of a state of charge shared by several devices, so its scheduled state of charge no longer drifts above the one the scheduler planned with [see `PR #2838 `_] * Hovering anywhere over a session in the Charge Points chart shows its tooltip again, listing all of the session's timestamps, as it did before the move to ECharts, without highlighting another charger's session; also, a chart's tooltip no longer shows a point from a neighbouring subplot [see `PR #2829 `_]