mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-05-01 11:19:32 -05:00
Allow webhook body
This commit is contained in:
parent
4f7cbab912
commit
02ff7bd55e
@ -336,7 +336,12 @@
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<pngx-input-text i18n-title title="Webhook url" formControlName="webhook_url" [error]="error?.actions?.[i]?.webhook_url"></pngx-input-text>
|
||||
<pngx-input-entries i18n-title title="Webhook params" formControlName="webhook_params" [error]="error?.actions?.[i]?.webhook_params"></pngx-input-entries>
|
||||
<pngx-input-switch i18n-title title="Use parameters for webhook body" formControlName="webhook_use_params"></pngx-input-switch>
|
||||
@if (formGroup.get('webhook_use_params').value) {
|
||||
<pngx-input-entries i18n-title title="Webhook params" formControlName="webhook_params" [error]="error?.actions?.[i]?.webhook_params"></pngx-input-entries>
|
||||
} @else {
|
||||
<pngx-input-textarea i18n-title title="Webhook body" formControlName="webhook_body" [error]="error?.actions?.[i]?.webhook_body"></pngx-input-textarea>
|
||||
}
|
||||
<pngx-input-entries i18n-title title="Webhook headers" formControlName="webhook_headers" [error]="error?.actions?.[i]?.webhook_headers"></pngx-input-entries>
|
||||
<pngx-input-switch i18n-title title="Include document" formControlName="webhook_include_document"></pngx-input-switch>
|
||||
</div>
|
||||
|
@ -415,7 +415,9 @@ export class WorkflowEditDialogComponent
|
||||
email_to: new FormControl(action.email_to),
|
||||
email_include_document: new FormControl(action.email_include_document),
|
||||
webhook_url: new FormControl(action.webhook_url),
|
||||
webhook_use_params: new FormControl(action.webhook_use_params),
|
||||
webhook_params: new FormControl(action.webhook_params),
|
||||
webhook_body: new FormControl(action.webhook_body),
|
||||
webhook_headers: new FormControl(action.webhook_headers),
|
||||
webhook_include_document: new FormControl(
|
||||
action.webhook_include_document
|
||||
@ -526,7 +528,9 @@ export class WorkflowEditDialogComponent
|
||||
email_to: null,
|
||||
email_include_document: false,
|
||||
webhook_url: null,
|
||||
webhook_use_params: true,
|
||||
webhook_params: null,
|
||||
webhook_body: null,
|
||||
webhook_headers: null,
|
||||
webhook_include_document: false,
|
||||
}
|
||||
|
@ -75,8 +75,12 @@ export interface WorkflowAction extends ObjectWithId {
|
||||
|
||||
webhook_url?: string
|
||||
|
||||
webhook_use_params?: boolean
|
||||
|
||||
webhook_params?: object
|
||||
|
||||
webhook_body?: string
|
||||
|
||||
webhook_headers?: object
|
||||
|
||||
webhook_include_document?: boolean
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.1.1 on 2024-11-02 15:25
|
||||
# Generated by Django 5.1.1 on 2024-11-06 20:45
|
||||
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
@ -49,6 +49,16 @@ class Migration(migrations.Migration):
|
||||
verbose_name="emails to",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="workflowaction",
|
||||
name="webhook_body",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="The body to send with the webhook URL if parameters not used.",
|
||||
null=True,
|
||||
verbose_name="webhook body",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="workflowaction",
|
||||
name="webhook_headers",
|
||||
@ -72,7 +82,7 @@ class Migration(migrations.Migration):
|
||||
name="webhook_params",
|
||||
field=models.JSONField(
|
||||
blank=True,
|
||||
help_text="The parameters to send with the webhook URL.",
|
||||
help_text="The parameters to send with the webhook URL if body not used.",
|
||||
null=True,
|
||||
verbose_name="webhook parameters",
|
||||
),
|
||||
@ -87,6 +97,11 @@ class Migration(migrations.Migration):
|
||||
verbose_name="webhook url",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="workflowaction",
|
||||
name="webhook_use_params",
|
||||
field=models.BooleanField(default=True, verbose_name="use parameters"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="workflowaction",
|
||||
name="type",
|
||||
|
@ -1417,11 +1417,23 @@ class WorkflowAction(models.Model):
|
||||
help_text=_("The destination URL for the notification."),
|
||||
)
|
||||
|
||||
webhook_use_params = models.BooleanField(
|
||||
default=True,
|
||||
verbose_name=_("use parameters"),
|
||||
)
|
||||
|
||||
webhook_params = models.JSONField(
|
||||
_("webhook parameters"),
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text=_("The parameters to send with the webhook URL."),
|
||||
help_text=_("The parameters to send with the webhook URL if body not used."),
|
||||
)
|
||||
|
||||
webhook_body = models.TextField(
|
||||
_("webhook body"),
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text=_("The body to send with the webhook URL if parameters not used."),
|
||||
)
|
||||
|
||||
webhook_headers = models.JSONField(
|
||||
|
@ -1852,7 +1852,9 @@ class WorkflowActionSerializer(serializers.ModelSerializer):
|
||||
"email_body",
|
||||
"email_include_document",
|
||||
"webhook_url",
|
||||
"webhook_use_params",
|
||||
"webhook_params",
|
||||
"webhook_body",
|
||||
"webhook_headers",
|
||||
]
|
||||
|
||||
|
@ -936,24 +936,41 @@ def run_workflows(
|
||||
doc_url = f"{settings.PAPERLESS_URL}/documents/{document.pk}/"
|
||||
|
||||
try:
|
||||
params = {}
|
||||
try:
|
||||
for key, value in action.webhook_params.items():
|
||||
params[key] = parse_w_workflow_placeholders(
|
||||
value,
|
||||
document.correspondent.name if document.correspondent else "",
|
||||
document.document_type.name if document.document_type else "",
|
||||
document.owner.username if document.owner else "",
|
||||
timezone.localtime(document.added),
|
||||
document.original_filename or "",
|
||||
timezone.localtime(document.created),
|
||||
title,
|
||||
doc_url,
|
||||
data = {}
|
||||
if action.webhook_use_params:
|
||||
try:
|
||||
for key, value in action.webhook_params.items():
|
||||
data[key] = parse_w_workflow_placeholders(
|
||||
value,
|
||||
document.correspondent.name
|
||||
if document.correspondent
|
||||
else "",
|
||||
document.document_type.name
|
||||
if document.document_type
|
||||
else "",
|
||||
document.owner.username if document.owner else "",
|
||||
timezone.localtime(document.added),
|
||||
document.original_filename or "",
|
||||
timezone.localtime(document.created),
|
||||
title,
|
||||
doc_url,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Error occurred parsing webhook params: {e}",
|
||||
extra={"group": logging_group},
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Error occurred parsing webhook params: {e}",
|
||||
extra={"group": logging_group},
|
||||
else:
|
||||
data = parse_w_workflow_placeholders(
|
||||
action.webhook_body,
|
||||
document.correspondent.name if document.correspondent else "",
|
||||
document.document_type.name if document.document_type else "",
|
||||
document.owner.username if document.owner else "",
|
||||
timezone.localtime(document.added),
|
||||
document.original_filename or "",
|
||||
timezone.localtime(document.created),
|
||||
title,
|
||||
doc_url,
|
||||
)
|
||||
headers = {}
|
||||
if action.webhook_headers:
|
||||
@ -971,14 +988,14 @@ def run_workflows(
|
||||
files = {"file": (document.original_filename, f)}
|
||||
httpx.post(
|
||||
action.webhook_url,
|
||||
data=params,
|
||||
data=data,
|
||||
files=files,
|
||||
headers=headers,
|
||||
)
|
||||
else:
|
||||
httpx.post(
|
||||
action.webhook_url,
|
||||
data=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
)
|
||||
except Exception as e:
|
||||
|
@ -2228,6 +2228,58 @@ class TestWorkflows(
|
||||
expected_str = "Email backend has not been configured"
|
||||
self.assertIn(expected_str, cm.output[0])
|
||||
|
||||
@override_settings(
|
||||
PAPERLESS_EMAIL_HOST="localhost",
|
||||
EMAIL_ENABLED=True,
|
||||
PAPERLESS_URL="http://localhost:8000",
|
||||
)
|
||||
@mock.patch("httpx.post")
|
||||
def test_workflow_webhook_action_body(self, mock_post):
|
||||
"""
|
||||
GIVEN:
|
||||
- Document updated workflow with webhook action which uses body
|
||||
WHEN:
|
||||
- Document that matches is updated
|
||||
THEN:
|
||||
- Webhook is sent with body
|
||||
"""
|
||||
mock_post.return_value = mock.Mock(
|
||||
status_code=200,
|
||||
json=mock.Mock(return_value={"status": "ok"}),
|
||||
)
|
||||
|
||||
trigger = WorkflowTrigger.objects.create(
|
||||
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
|
||||
)
|
||||
action = WorkflowAction.objects.create(
|
||||
type=WorkflowAction.WorkflowActionType.WEBHOOK,
|
||||
webhook_use_params=False,
|
||||
webhook_body="Test message: {doc_url}",
|
||||
webhook_url="http://paperless-ngx.com",
|
||||
webhook_include_document=False,
|
||||
)
|
||||
w = Workflow.objects.create(
|
||||
name="Workflow 1",
|
||||
order=0,
|
||||
)
|
||||
w.triggers.add(trigger)
|
||||
w.actions.add(action)
|
||||
w.save()
|
||||
|
||||
doc = Document.objects.create(
|
||||
title="sample test",
|
||||
correspondent=self.c,
|
||||
original_filename="sample.pdf",
|
||||
)
|
||||
|
||||
run_workflows(WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED, doc)
|
||||
|
||||
mock_post.assert_called_once_with(
|
||||
"http://paperless-ngx.com",
|
||||
data=f"Test message: http://localhost:8000/documents/{doc.id}/",
|
||||
headers={},
|
||||
)
|
||||
|
||||
@override_settings(
|
||||
PAPERLESS_EMAIL_HOST="localhost",
|
||||
EMAIL_ENABLED=True,
|
||||
@ -2248,6 +2300,7 @@ class TestWorkflows(
|
||||
)
|
||||
action = WorkflowAction.objects.create(
|
||||
type=WorkflowAction.WorkflowActionType.WEBHOOK,
|
||||
webhook_use_params=True,
|
||||
webhook_params={
|
||||
"title": "Test webhook: {doc_title}",
|
||||
"body": "Test message: {doc_url}",
|
||||
@ -2277,7 +2330,7 @@ class TestWorkflows(
|
||||
self.assertIn(expected_str, cm.output[0])
|
||||
|
||||
@mock.patch("httpx.post")
|
||||
def test_workflow_notification_action_url_invalid_params_headers(self, mock_post):
|
||||
def test_workflow_webhook_action_url_invalid_params_headers(self, mock_post):
|
||||
"""
|
||||
GIVEN:
|
||||
- Document updated workflow with webhook action
|
||||
@ -2293,6 +2346,7 @@ class TestWorkflows(
|
||||
action = WorkflowAction.objects.create(
|
||||
type=WorkflowAction.WorkflowActionType.WEBHOOK,
|
||||
webhook_url="http://paperless-ngx.com",
|
||||
webhook_use_params=True,
|
||||
webhook_params="invalid",
|
||||
webhook_headers="invalid",
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user