mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-02-18 00:29:35 -06:00
Backend doc updated ws
This commit is contained in:
@@ -15,6 +15,7 @@ class DocumentsConfig(AppConfig):
|
|||||||
from documents.signals.handlers import add_to_index
|
from documents.signals.handlers import add_to_index
|
||||||
from documents.signals.handlers import run_workflows_added
|
from documents.signals.handlers import run_workflows_added
|
||||||
from documents.signals.handlers import run_workflows_updated
|
from documents.signals.handlers import run_workflows_updated
|
||||||
|
from documents.signals.handlers import send_websocket_document_updated
|
||||||
from documents.signals.handlers import set_correspondent
|
from documents.signals.handlers import set_correspondent
|
||||||
from documents.signals.handlers import set_document_type
|
from documents.signals.handlers import set_document_type
|
||||||
from documents.signals.handlers import set_storage_path
|
from documents.signals.handlers import set_storage_path
|
||||||
@@ -29,6 +30,7 @@ class DocumentsConfig(AppConfig):
|
|||||||
document_consumption_finished.connect(run_workflows_added)
|
document_consumption_finished.connect(run_workflows_added)
|
||||||
document_consumption_finished.connect(add_or_update_document_in_llm_index)
|
document_consumption_finished.connect(add_or_update_document_in_llm_index)
|
||||||
document_updated.connect(run_workflows_updated)
|
document_updated.connect(run_workflows_updated)
|
||||||
|
document_updated.connect(send_websocket_document_updated)
|
||||||
|
|
||||||
import documents.schema # noqa: F401
|
import documents.schema # noqa: F401
|
||||||
|
|
||||||
|
|||||||
@@ -100,3 +100,25 @@ class DocumentsStatusManager(BaseStatusManager):
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.send(payload)
|
self.send(payload)
|
||||||
|
|
||||||
|
def send_document_updated(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
document_id: int,
|
||||||
|
modified: str | None = None,
|
||||||
|
owner_id: int | None = None,
|
||||||
|
users_can_view: list[int] | None = None,
|
||||||
|
groups_can_view: list[int] | None = None,
|
||||||
|
) -> None:
|
||||||
|
payload = {
|
||||||
|
"type": "document_updated",
|
||||||
|
"data": {
|
||||||
|
"document_id": document_id,
|
||||||
|
"modified": modified,
|
||||||
|
"owner_id": owner_id,
|
||||||
|
"users_can_view": users_can_view or [],
|
||||||
|
"groups_can_view": groups_can_view or [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
self.send(payload)
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ from documents.models import WorkflowAction
|
|||||||
from documents.models import WorkflowRun
|
from documents.models import WorkflowRun
|
||||||
from documents.models import WorkflowTrigger
|
from documents.models import WorkflowTrigger
|
||||||
from documents.permissions import get_objects_for_user_owner_aware
|
from documents.permissions import get_objects_for_user_owner_aware
|
||||||
|
from documents.plugins.helpers import DocumentsStatusManager
|
||||||
from documents.templating.utils import convert_format_str_to_template_format
|
from documents.templating.utils import convert_format_str_to_template_format
|
||||||
from documents.workflows.actions import build_workflow_action_context
|
from documents.workflows.actions import build_workflow_action_context
|
||||||
from documents.workflows.actions import execute_email_action
|
from documents.workflows.actions import execute_email_action
|
||||||
@@ -753,6 +754,28 @@ def run_workflows_updated(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def send_websocket_document_updated(
|
||||||
|
sender,
|
||||||
|
document: Document,
|
||||||
|
**kwargs,
|
||||||
|
) -> None:
|
||||||
|
# At this point, workflows may already have applied additional changes.
|
||||||
|
document.refresh_from_db()
|
||||||
|
|
||||||
|
from documents.data_models import DocumentMetadataOverrides
|
||||||
|
|
||||||
|
doc_overrides = DocumentMetadataOverrides.from_document(document)
|
||||||
|
|
||||||
|
with DocumentsStatusManager() as status_mgr:
|
||||||
|
status_mgr.send_document_updated(
|
||||||
|
document_id=document.id,
|
||||||
|
modified=document.modified.isoformat() if document.modified else None,
|
||||||
|
owner_id=doc_overrides.owner_id,
|
||||||
|
users_can_view=doc_overrides.view_users,
|
||||||
|
groups_can_view=doc_overrides.view_groups,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def run_workflows(
|
def run_workflows(
|
||||||
trigger_type: WorkflowTrigger.WorkflowTriggerType,
|
trigger_type: WorkflowTrigger.WorkflowTriggerType,
|
||||||
document: Document | ConsumableDocument,
|
document: Document | ConsumableDocument,
|
||||||
|
|||||||
@@ -52,3 +52,10 @@ class StatusConsumer(WebsocketConsumer):
|
|||||||
self.close()
|
self.close()
|
||||||
else:
|
else:
|
||||||
self.send(json.dumps(event))
|
self.send(json.dumps(event))
|
||||||
|
|
||||||
|
def document_updated(self, event) -> None:
|
||||||
|
if not self._authenticated():
|
||||||
|
self.close()
|
||||||
|
else:
|
||||||
|
if self._can_view(event["data"]):
|
||||||
|
self.send(json.dumps(event))
|
||||||
|
|||||||
@@ -158,6 +158,39 @@ class TestWebSockets(TestCase):
|
|||||||
|
|
||||||
await communicator.disconnect()
|
await communicator.disconnect()
|
||||||
|
|
||||||
|
@mock.patch("paperless.consumers.StatusConsumer._can_view")
|
||||||
|
@mock.patch("paperless.consumers.StatusConsumer._authenticated")
|
||||||
|
async def test_receive_document_updated(self, _authenticated, _can_view) -> None:
|
||||||
|
_authenticated.return_value = True
|
||||||
|
_can_view.return_value = True
|
||||||
|
|
||||||
|
communicator = WebsocketCommunicator(application, "/ws/status/")
|
||||||
|
connected, _ = await communicator.connect()
|
||||||
|
self.assertTrue(connected)
|
||||||
|
|
||||||
|
message = {
|
||||||
|
"type": "document_updated",
|
||||||
|
"data": {
|
||||||
|
"document_id": 10,
|
||||||
|
"modified": "2026-02-17T00:00:00Z",
|
||||||
|
"owner_id": 1,
|
||||||
|
"users_can_view": [1],
|
||||||
|
"groups_can_view": [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
channel_layer = get_channel_layer()
|
||||||
|
await channel_layer.group_send(
|
||||||
|
"status_updates",
|
||||||
|
message,
|
||||||
|
)
|
||||||
|
|
||||||
|
response = await communicator.receive_json_from()
|
||||||
|
|
||||||
|
self.assertEqual(response, message)
|
||||||
|
|
||||||
|
await communicator.disconnect()
|
||||||
|
|
||||||
@mock.patch("channels.layers.InMemoryChannelLayer.group_send")
|
@mock.patch("channels.layers.InMemoryChannelLayer.group_send")
|
||||||
def test_manager_send_progress(self, mock_group_send) -> None:
|
def test_manager_send_progress(self, mock_group_send) -> None:
|
||||||
with ProgressManager(task_id="test") as manager:
|
with ProgressManager(task_id="test") as manager:
|
||||||
|
|||||||
Reference in New Issue
Block a user