fix(files): align adaptive tasks with live access
This commit is contained in:
@@ -13,6 +13,7 @@ from govoplan_core.core.modules import (
|
|||||||
DocumentationTopic,
|
DocumentationTopic,
|
||||||
)
|
)
|
||||||
from govoplan_files.backend.storage.archives import ZIP_UPLOAD_MAX_FILES
|
from govoplan_files.backend.storage.archives import ZIP_UPLOAD_MAX_FILES
|
||||||
|
from govoplan_files.backend.storage.access import user_group_ids
|
||||||
from govoplan_files.backend.storage.connector_visibility import (
|
from govoplan_files.backend.storage.connector_visibility import (
|
||||||
connector_profile_usable_for_import,
|
connector_profile_usable_for_import,
|
||||||
visible_connector_profiles_for_actor,
|
visible_connector_profiles_for_actor,
|
||||||
@@ -90,7 +91,7 @@ def _upload_topic(max_bytes: int) -> DocumentationTopic:
|
|||||||
"help_contexts": ["files.list"],
|
"help_contexts": ["files.list"],
|
||||||
"prerequisites": [
|
"prerequisites": [
|
||||||
"You may view and upload managed files.",
|
"You may view and upload managed files.",
|
||||||
"You can access the destination personal or group space.",
|
"The destination personal or group space grants this account write access; upload permission alone does not grant access to every space.",
|
||||||
],
|
],
|
||||||
"steps": [
|
"steps": [
|
||||||
"Open Files and choose My files or an accessible group space.",
|
"Open Files and choose My files or an accessible group space.",
|
||||||
@@ -161,6 +162,7 @@ def _zip_topic(max_file_bytes: int, max_zip_bytes: int) -> DocumentationTopic:
|
|||||||
"prerequisites": [
|
"prerequisites": [
|
||||||
"You may view and upload managed files.",
|
"You may view and upload managed files.",
|
||||||
"The archive is not encrypted and fits the current configured limits.",
|
"The archive is not encrypted and fits the current configured limits.",
|
||||||
|
"The destination personal or group space grants this account write access.",
|
||||||
],
|
],
|
||||||
"steps": [
|
"steps": [
|
||||||
"Open Files and choose the managed destination space and folder.",
|
"Open Files and choose the managed destination space and folder.",
|
||||||
@@ -215,19 +217,36 @@ def _connector_import_topic(context: DocumentationContext) -> DocumentationTopic
|
|||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
group_ids = _principal_group_ids(principal)
|
member_group_ids = _actor_group_ids(
|
||||||
|
session,
|
||||||
|
principal=principal,
|
||||||
|
tenant_id=tenant_id,
|
||||||
|
user_id=user_id,
|
||||||
|
include_admin_groups=False,
|
||||||
|
)
|
||||||
|
connector_group_ids = (
|
||||||
|
_actor_group_ids(
|
||||||
|
session,
|
||||||
|
principal=principal,
|
||||||
|
tenant_id=tenant_id,
|
||||||
|
user_id=user_id,
|
||||||
|
include_admin_groups=True,
|
||||||
|
)
|
||||||
|
if _has_all_scopes(principal, ("files:file:admin",))
|
||||||
|
else member_group_ids
|
||||||
|
)
|
||||||
profiles = visible_connector_profiles_for_actor(
|
profiles = visible_connector_profiles_for_actor(
|
||||||
session,
|
session,
|
||||||
tenant_id=tenant_id,
|
tenant_id=tenant_id,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
group_ids=group_ids,
|
group_ids=connector_group_ids,
|
||||||
settings=context.settings,
|
settings=context.settings,
|
||||||
campaign_visible=_campaign_visibility(
|
campaign_visible=_campaign_visibility(
|
||||||
context,
|
context,
|
||||||
session=session,
|
session=session,
|
||||||
tenant_id=tenant_id,
|
tenant_id=tenant_id,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
group_ids=group_ids,
|
group_ids=member_group_ids,
|
||||||
),
|
),
|
||||||
include_effective_policy=True,
|
include_effective_policy=True,
|
||||||
)
|
)
|
||||||
@@ -286,6 +305,7 @@ def _connector_import_topic(context: DocumentationContext) -> DocumentationTopic
|
|||||||
"You may view and upload managed files.",
|
"You may view and upload managed files.",
|
||||||
"At least one enabled, credential-ready, policy-allowed connection using a pinning-safe provider is visible to this account.",
|
"At least one enabled, credential-ready, policy-allowed connection using a pinning-safe provider is visible to this account.",
|
||||||
"The selected remote path and item must pass their operation-time policy checks.",
|
"The selected remote path and item must pass their operation-time policy checks.",
|
||||||
|
"The managed destination space grants this account write access.",
|
||||||
],
|
],
|
||||||
"steps": [
|
"steps": [
|
||||||
"Open Files and choose a managed destination space.",
|
"Open Files and choose a managed destination space.",
|
||||||
@@ -382,6 +402,26 @@ def _principal_group_ids(principal: object) -> tuple[str, ...]:
|
|||||||
return tuple(str(value) for value in values if str(value))
|
return tuple(str(value) for value in values if str(value))
|
||||||
|
|
||||||
|
|
||||||
|
def _actor_group_ids(
|
||||||
|
session: Session,
|
||||||
|
*,
|
||||||
|
principal: object,
|
||||||
|
tenant_id: str,
|
||||||
|
user_id: str,
|
||||||
|
include_admin_groups: bool,
|
||||||
|
) -> tuple[str, ...]:
|
||||||
|
try:
|
||||||
|
values = user_group_ids(
|
||||||
|
session,
|
||||||
|
tenant_id=tenant_id,
|
||||||
|
user_id=user_id,
|
||||||
|
include_admin_groups=include_admin_groups,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
return _principal_group_ids(principal)
|
||||||
|
return tuple(str(value) for value in values if str(value))
|
||||||
|
|
||||||
|
|
||||||
def _campaign_visibility(
|
def _campaign_visibility(
|
||||||
context: DocumentationContext,
|
context: DocumentationContext,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ manifest = ModuleManifest(
|
|||||||
"help_contexts": ["files.list"],
|
"help_contexts": ["files.list"],
|
||||||
"prerequisites": [
|
"prerequisites": [
|
||||||
"You may view and organize managed files.",
|
"You may view and organize managed files.",
|
||||||
"You can access every source and destination space used by the operation.",
|
"You have write or owner access to every source item and destination space used by the operation; the global organize permission alone does not grant resource access.",
|
||||||
],
|
],
|
||||||
"steps": [
|
"steps": [
|
||||||
"Open Files and select the personal or group space to organize.",
|
"Open Files and select the personal or group space to organize.",
|
||||||
@@ -317,7 +317,7 @@ manifest = ModuleManifest(
|
|||||||
"screen": "Files",
|
"screen": "Files",
|
||||||
"help_contexts": ["files.list"],
|
"help_contexts": ["files.list"],
|
||||||
"prerequisites": [
|
"prerequisites": [
|
||||||
"You may view and share the managed file.",
|
"You may view and share the managed file and have write/manage access to that specific asset; the global share permission alone does not grant resource access.",
|
||||||
"A supporting workflow or API client is available; the Files page has no general share editor yet.",
|
"A supporting workflow or API client is available; the Files page has no general share editor yet.",
|
||||||
"The process does not require share revocation, because no revocation route exists yet.",
|
"The process does not require share revocation, because no revocation route exists yet.",
|
||||||
],
|
],
|
||||||
@@ -368,7 +368,7 @@ manifest = ModuleManifest(
|
|||||||
"screen": "Files",
|
"screen": "Files",
|
||||||
"help_contexts": ["files.list"],
|
"help_contexts": ["files.list"],
|
||||||
"prerequisites": [
|
"prerequisites": [
|
||||||
"You may view and delete the selected managed content.",
|
"You may view and delete the selected managed content and have write or owner access to every affected asset or folder.",
|
||||||
"You have reviewed the complete folder tree when deleting recursively.",
|
"You have reviewed the complete folder tree when deleting recursively.",
|
||||||
],
|
],
|
||||||
"steps": [
|
"steps": [
|
||||||
|
|||||||
@@ -160,6 +160,57 @@ class FilesRuntimeDocumentationTests(unittest.TestCase):
|
|||||||
):
|
):
|
||||||
self.assertNotIn(secret, payload)
|
self.assertNotIn(secret, payload)
|
||||||
|
|
||||||
|
def test_files_admin_connector_groups_do_not_widen_campaign_membership(self) -> None:
|
||||||
|
usable = ConnectorProfile(
|
||||||
|
id="group-profile",
|
||||||
|
label="Group profile",
|
||||||
|
provider="webdav",
|
||||||
|
scope_type="group",
|
||||||
|
scope_id="admin-visible-group",
|
||||||
|
endpoint_url="https://files.example.invalid",
|
||||||
|
credential_mode="anonymous",
|
||||||
|
)
|
||||||
|
|
||||||
|
def groups_for_actor(_session, *, include_admin_groups, **_kwargs):
|
||||||
|
return ["member-group", "admin-visible-group"] if include_admin_groups else ["member-group"]
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"govoplan_files.backend.documentation.user_group_ids",
|
||||||
|
side_effect=groups_for_actor,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"govoplan_files.backend.documentation._campaign_visibility",
|
||||||
|
return_value=None,
|
||||||
|
) as campaign_visibility,
|
||||||
|
patch(
|
||||||
|
"govoplan_files.backend.documentation.visible_connector_profiles_for_actor",
|
||||||
|
return_value=[usable],
|
||||||
|
) as visible,
|
||||||
|
):
|
||||||
|
topics = {
|
||||||
|
topic.id: topic
|
||||||
|
for topic in documentation_topics(
|
||||||
|
self.context(
|
||||||
|
{
|
||||||
|
"files:file:read",
|
||||||
|
"files:file:upload",
|
||||||
|
"files:file:admin",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertIn("files.workflow.import-managed-snapshot", topics)
|
||||||
|
self.assertEqual(
|
||||||
|
("member-group", "admin-visible-group"),
|
||||||
|
tuple(visible.call_args.kwargs["group_ids"]),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
("member-group",),
|
||||||
|
tuple(campaign_visibility.call_args.kwargs["group_ids"]),
|
||||||
|
)
|
||||||
|
|
||||||
def test_connector_evaluation_errors_fail_closed_without_error_details(
|
def test_connector_evaluation_errors_fail_closed_without_error_details(
|
||||||
self,
|
self,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user