Use discreet model for email / webhook

This commit is contained in:
shamoon 2024-11-25 21:09:13 -08:00
parent 69a4331d99
commit 6b36ee7819
No known key found for this signature in database
11 changed files with 501 additions and 323 deletions

View File

@ -323,27 +323,29 @@
</div>
}
@case (WorkflowActionType.Email) {
<div class="row">
<div class="row" [formGroup]="formGroup.get('email')">
<input type="hidden" formControlName="id" />
<div class="col">
<pngx-input-text i18n-title title="Email subject" formControlName="email_subject" [error]="error?.actions?.[i]?.email_subject"></pngx-input-text>
<pngx-input-textarea i18n-title title="Email body" formControlName="email_body" [error]="error?.actions?.[i]?.email_body"></pngx-input-textarea>
<pngx-input-text i18n-title title="Email recipients" formControlName="email_to" [error]="error?.actions?.[i]?.email_to"></pngx-input-text>
<pngx-input-switch i18n-title title="Attach document" formControlName="email_include_document"></pngx-input-switch>
<pngx-input-text i18n-title title="Email subject" formControlName="subject" [error]="error?.actions?.[i]?.email?.subject"></pngx-input-text>
<pngx-input-textarea i18n-title title="Email body" formControlName="body" [error]="error?.actions?.[i]?.email?.body"></pngx-input-textarea>
<pngx-input-text i18n-title title="Email recipients" formControlName="to" [error]="error?.actions?.[i]?.email?.to"></pngx-input-text>
<pngx-input-switch i18n-title title="Attach document" formControlName="include_document"></pngx-input-switch>
</div>
</div>
}
@case (WorkflowActionType.Webhook) {
<div class="row">
<div class="row" [formGroup]="formGroup.get('webhook')">
<input type="hidden" formControlName="id" />
<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-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>
<pngx-input-text i18n-title title="Webhook url" formControlName="url" [error]="error?.actions?.[i]?.url"></pngx-input-text>
<pngx-input-switch i18n-title title="Use parameters for webhook body" formControlName="use_params"></pngx-input-switch>
@if (formGroup.get('webhook').value['use_params']) {
<pngx-input-entries i18n-title title="Webhook params" formControlName="params" [error]="error?.actions?.[i]?.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-textarea i18n-title title="Webhook body" formControlName="body" [error]="error?.actions?.[i]?.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>
<pngx-input-entries i18n-title title="Webhook headers" formControlName="headers" [error]="error?.actions?.[i]?.headers"></pngx-input-entries>
<pngx-input-switch i18n-title title="Include document" formControlName="include_document"></pngx-input-switch>
</div>
</div>
}

View File

@ -347,4 +347,15 @@ describe('WorkflowEditDialogComponent', () => {
component.actionFields.at(0).get('remove_change_groups').disabled
).toBeFalsy()
})
it('should prune empty nested objects on save', () => {
component.object = workflow
component.addTrigger()
component.addAction()
expect(component.objectForm.get('actions').value[0].email).not.toBeNull()
expect(component.objectForm.get('actions').value[0].webhook).not.toBeNull()
component.save()
expect(component.objectForm.get('actions').value[0].email).toBeNull()
expect(component.objectForm.get('actions').value[0].webhook).toBeNull()
})
})

View File

@ -410,18 +410,22 @@ export class WorkflowEditDialogComponent
remove_all_custom_fields: new FormControl(
action.remove_all_custom_fields
),
email_subject: new FormControl(action.email_subject),
email_body: new FormControl(action.email_body),
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
),
email: new FormGroup({
id: new FormControl(action.email?.id),
subject: new FormControl(action.email?.subject),
body: new FormControl(action.email?.body),
to: new FormControl(action.email?.to),
include_document: new FormControl(!!action.email?.include_document),
}),
webhook: new FormGroup({
id: new FormControl(action.webhook?.id),
url: new FormControl(action.webhook?.url),
use_params: new FormControl(action.webhook?.use_params),
params: new FormControl(action.webhook?.params),
body: new FormControl(action.webhook?.body),
headers: new FormControl(action.webhook?.headers),
include_document: new FormControl(!!action.webhook?.include_document),
}),
}),
{ emitEvent }
)
@ -523,16 +527,22 @@ export class WorkflowEditDialogComponent
remove_all_permissions: false,
remove_custom_fields: [],
remove_all_custom_fields: false,
email_subject: null,
email_body: null,
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,
email: {
id: null,
subject: null,
body: null,
to: null,
include_document: false,
},
webhook: {
id: null,
url: null,
use_params: true,
params: null,
body: null,
headers: null,
include_document: false,
},
}
this.object.actions.push(action)
this.createActionField(action)
@ -563,4 +573,18 @@ export class WorkflowEditDialogComponent
c.get('id').setValue(null, { emitEvent: false })
)
}
save(): void {
this.objectForm
.get('actions')
.value.forEach((action: WorkflowAction, i) => {
if (action.type !== WorkflowActionType.Webhook) {
action.webhook = null
}
if (action.type !== WorkflowActionType.Email) {
action.email = null
}
})
super.save()
}
}

View File

@ -6,6 +6,31 @@ export enum WorkflowActionType {
Email = 3,
Webhook = 4,
}
export interface WorkflowActionEmail extends ObjectWithId {
subject?: string
body?: string
to?: string
include_document?: boolean
}
export interface WorkflowActionWebhook extends ObjectWithId {
url?: string
use_params?: boolean
params?: object
body?: string
headers?: object
include_document?: boolean
}
export interface WorkflowAction extends ObjectWithId {
type: WorkflowActionType
@ -65,23 +90,7 @@ export interface WorkflowAction extends ObjectWithId {
remove_all_custom_fields?: boolean
email_subject?: string
email?: WorkflowActionEmail
email_body?: string
email_to?: string
email_include_document?: boolean
webhook_url?: string
webhook_use_params?: boolean
webhook_params?: object
webhook_body?: string
webhook_headers?: object
webhook_include_document?: boolean
webhook?: WorkflowActionWebhook
}

View File

@ -1,119 +0,0 @@
# Generated by Django 5.1.3 on 2024-11-24 18:30
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("documents", "1058_workflowtrigger_schedule_date_custom_field_and_more"),
]
operations = [
migrations.AddField(
model_name="workflowaction",
name="email_body",
field=models.TextField(
blank=True,
help_text="The body (message) of the email, can include some placeholders, see documentation.",
null=True,
verbose_name="email body",
),
),
migrations.AddField(
model_name="workflowaction",
name="email_include_document",
field=models.BooleanField(
default=False,
verbose_name="include document in email",
),
),
migrations.AddField(
model_name="workflowaction",
name="email_subject",
field=models.CharField(
blank=True,
help_text="The subject of the email, can include some placeholders, see documentation.",
max_length=256,
null=True,
verbose_name="email subject",
),
),
migrations.AddField(
model_name="workflowaction",
name="email_to",
field=models.TextField(
blank=True,
help_text="The destination email addresses, comma separated.",
null=True,
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",
field=models.JSONField(
blank=True,
help_text="The headers to send with the webhook URL.",
null=True,
verbose_name="webhook headers",
),
),
migrations.AddField(
model_name="workflowaction",
name="webhook_include_document",
field=models.BooleanField(
default=False,
verbose_name="include document in webhook",
),
),
migrations.AddField(
model_name="workflowaction",
name="webhook_params",
field=models.JSONField(
blank=True,
help_text="The parameters to send with the webhook URL if body not used.",
null=True,
verbose_name="webhook parameters",
),
),
migrations.AddField(
model_name="workflowaction",
name="webhook_url",
field=models.URLField(
blank=True,
help_text="The destination URL for the notification.",
null=True,
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",
field=models.PositiveIntegerField(
choices=[
(1, "Assignment"),
(2, "Removal"),
(3, "Email"),
(4, "Webhook"),
],
default=1,
verbose_name="Workflow Action Type",
),
),
]

View File

@ -0,0 +1,154 @@
# Generated by Django 5.1.3 on 2024-11-26 04:07
import django.db.models.deletion
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("documents", "1058_workflowtrigger_schedule_date_custom_field_and_more"),
]
operations = [
migrations.CreateModel(
name="WorkflowActionEmail",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"subject",
models.CharField(
help_text="The subject of the email, can include some placeholders, see documentation.",
max_length=256,
verbose_name="email subject",
),
),
(
"body",
models.TextField(
help_text="The body (message) of the email, can include some placeholders, see documentation.",
verbose_name="email body",
),
),
(
"to",
models.TextField(
help_text="The destination email addresses, comma separated.",
verbose_name="emails to",
),
),
(
"include_document",
models.BooleanField(
default=False,
verbose_name="include document in email",
),
),
],
),
migrations.CreateModel(
name="WorkflowActionWebhook",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"url",
models.URLField(
help_text="The destination URL for the notification.",
verbose_name="webhook url",
),
),
(
"use_params",
models.BooleanField(default=True, verbose_name="use parameters"),
),
(
"params",
models.JSONField(
blank=True,
help_text="The parameters to send with the webhook URL if body not used.",
null=True,
verbose_name="webhook parameters",
),
),
(
"body",
models.TextField(
blank=True,
help_text="The body to send with the webhook URL if parameters not used.",
null=True,
verbose_name="webhook body",
),
),
(
"headers",
models.JSONField(
blank=True,
help_text="The headers to send with the webhook URL.",
null=True,
verbose_name="webhook headers",
),
),
(
"include_document",
models.BooleanField(
default=False,
verbose_name="include document in webhook",
),
),
],
),
migrations.AlterField(
model_name="workflowaction",
name="type",
field=models.PositiveIntegerField(
choices=[
(1, "Assignment"),
(2, "Removal"),
(3, "Email"),
(4, "Webhook"),
],
default=1,
verbose_name="Workflow Action Type",
),
),
migrations.AddField(
model_name="workflowaction",
name="email",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="action",
to="documents.workflowactionemail",
verbose_name="email",
),
),
migrations.AddField(
model_name="workflowaction",
name="webhook",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="action",
to="documents.workflowactionwebhook",
verbose_name="webhook",
),
),
]

View File

@ -1156,6 +1156,85 @@ class WorkflowTrigger(models.Model):
return f"WorkflowTrigger {self.pk}"
class WorkflowActionEmail(models.Model):
subject = models.CharField(
_("email subject"),
max_length=256,
null=False,
help_text=_(
"The subject of the email, can include some placeholders, "
"see documentation.",
),
)
body = models.TextField(
_("email body"),
null=False,
help_text=_(
"The body (message) of the email, can include some placeholders, "
"see documentation.",
),
)
to = models.TextField(
_("emails to"),
null=False,
help_text=_(
"The destination email addresses, comma separated.",
),
)
include_document = models.BooleanField(
default=False,
verbose_name=_("include document in email"),
)
def __str__(self):
return f"Workflow Email Action {self.pk}"
class WorkflowActionWebhook(models.Model):
url = models.URLField(
_("webhook url"),
null=False,
help_text=_("The destination URL for the notification."),
)
use_params = models.BooleanField(
default=True,
verbose_name=_("use parameters"),
)
params = models.JSONField(
_("webhook parameters"),
null=True,
blank=True,
help_text=_("The parameters to send with the webhook URL if body not used."),
)
body = models.TextField(
_("webhook body"),
null=True,
blank=True,
help_text=_("The body to send with the webhook URL if parameters not used."),
)
headers = models.JSONField(
_("webhook headers"),
null=True,
blank=True,
help_text=_("The headers to send with the webhook URL."),
)
include_document = models.BooleanField(
default=False,
verbose_name=_("include document in webhook"),
)
def __str__(self):
return f"Workflow Webhook Action {self.pk}"
class WorkflowAction(models.Model):
class WorkflowActionType(models.IntegerChoices):
ASSIGNMENT = (
@ -1375,77 +1454,22 @@ class WorkflowAction(models.Model):
verbose_name=_("remove all custom fields"),
)
email_subject = models.CharField(
_("email subject"),
max_length=256,
email = models.ForeignKey(
WorkflowActionEmail,
null=True,
blank=True,
help_text=_(
"The subject of the email, can include some placeholders, "
"see documentation.",
),
on_delete=models.SET_NULL,
related_name="action",
verbose_name=_("email"),
)
email_body = models.TextField(
_("email body"),
webhook = models.ForeignKey(
WorkflowActionWebhook,
null=True,
blank=True,
help_text=_(
"The body (message) of the email, can include some placeholders, "
"see documentation.",
),
)
email_to = models.TextField(
_("emails to"),
null=True,
blank=True,
help_text=_(
"The destination email addresses, comma separated.",
),
)
email_include_document = models.BooleanField(
default=False,
verbose_name=_("include document in email"),
)
webhook_url = models.URLField(
_("webhook url"),
null=True,
blank=True,
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 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(
_("webhook headers"),
null=True,
blank=True,
help_text=_("The headers to send with the webhook URL."),
)
webhook_include_document = models.BooleanField(
default=False,
verbose_name=_("include document in webhook"),
on_delete=models.SET_NULL,
related_name="action",
verbose_name=_("webhook"),
)
class Meta:

View File

@ -49,6 +49,8 @@ from documents.models import Tag
from documents.models import UiSettings
from documents.models import Workflow
from documents.models import WorkflowAction
from documents.models import WorkflowActionEmail
from documents.models import WorkflowActionWebhook
from documents.models import WorkflowTrigger
from documents.parsers import is_mime_type_supported
from documents.permissions import get_groups_with_only_permission
@ -1807,12 +1809,44 @@ class WorkflowTriggerSerializer(serializers.ModelSerializer):
return attrs
class WorkflowActionEmailSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(allow_null=True, required=False)
class Meta:
model = WorkflowActionEmail
fields = [
"id",
"subject",
"body",
"to",
"include_document",
]
class WorkflowActionWebhookSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(allow_null=True, required=False)
class Meta:
model = WorkflowActionWebhook
fields = [
"id",
"url",
"use_params",
"params",
"body",
"headers",
"include_document",
]
class WorkflowActionSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False, allow_null=True)
assign_correspondent = CorrespondentField(allow_null=True, required=False)
assign_tags = TagsField(many=True, allow_null=True, required=False)
assign_document_type = DocumentTypeField(allow_null=True, required=False)
assign_storage_path = StoragePathField(allow_null=True, required=False)
email = WorkflowActionEmailSerializer(allow_null=True, required=False)
webhook = WorkflowActionWebhookSerializer(allow_null=True, required=False)
class Meta:
model = WorkflowAction
@ -1847,15 +1881,8 @@ class WorkflowActionSerializer(serializers.ModelSerializer):
"remove_view_groups",
"remove_change_users",
"remove_change_groups",
"email_to",
"email_subject",
"email_body",
"email_include_document",
"webhook_url",
"webhook_use_params",
"webhook_params",
"webhook_body",
"webhook_headers",
"email",
"webhook",
]
def validate(self, attrs):
@ -1893,37 +1920,22 @@ class WorkflowActionSerializer(serializers.ModelSerializer):
{"assign_title": f'Invalid f-string detected: "{e.args[0]}"'},
)
if "type" in attrs and attrs["type"] == WorkflowAction.WorkflowActionType.EMAIL:
if (
"email_subject" not in attrs
or attrs["email_subject"] is None
or len(attrs["email_subject"]) == 0
or "email_body" not in attrs
or attrs["email_body"] is None
or len(attrs["email_body"]) == 0
"type" in attrs
and attrs["type"] == WorkflowAction.WorkflowActionType.EMAIL
and "email" not in attrs
):
raise serializers.ValidationError(
"Email subject and body required",
)
elif (
"email_to" not in attrs
or attrs["email_to"] is None
or len(attrs["email_to"]) == 0
):
raise serializers.ValidationError(
"Email recipient required",
"Email data is required for email actions",
)
if (
"type" in attrs
and attrs["type"] == WorkflowAction.WorkflowActionType.WEBHOOK
) and (
"webhook_url" not in attrs
or attrs["webhook_url"] is None
or len(attrs["webhook_url"]) == 0
and "webhook" not in attrs
):
raise serializers.ValidationError(
"Webhook URL required",
"Webhook data is required for webhook actions",
)
return attrs
@ -1980,11 +1992,34 @@ class WorkflowSerializer(serializers.ModelSerializer):
remove_change_users = action.pop("remove_change_users", None)
remove_change_groups = action.pop("remove_change_groups", None)
email_data = action.pop("email", None)
webhook_data = action.pop("webhook", None)
action_instance, _ = WorkflowAction.objects.update_or_create(
id=action.get("id"),
defaults=action,
)
if email_data is not None:
serializer = WorkflowActionEmailSerializer(data=email_data)
serializer.is_valid(raise_exception=True)
email, _ = WorkflowActionEmail.objects.update_or_create(
id=email_data.get("id"),
defaults=serializer.validated_data,
)
action_instance.email = email
action_instance.save()
if webhook_data is not None:
serializer = WorkflowActionWebhookSerializer(data=webhook_data)
serializer.is_valid(raise_exception=True)
webhook, _ = WorkflowActionWebhook.objects.update_or_create(
id=webhook_data.get("id"),
defaults=serializer.validated_data,
)
action_instance.webhook = webhook
action_instance.save()
if assign_tags is not None:
action_instance.assign_tags.set(assign_tags)
if assign_view_users is not None:
@ -2037,6 +2072,9 @@ class WorkflowSerializer(serializers.ModelSerializer):
if action.workflows.all().count() == 0:
action.delete()
WorkflowActionEmail.objects.filter(action=None).delete()
WorkflowActionWebhook.objects.filter(action=None).delete()
def create(self, validated_data) -> Workflow:
if "triggers" in validated_data:
triggers = validated_data.pop("triggers")

View File

@ -891,7 +891,7 @@ def run_workflows(
added = timezone.localtime(document.added)
created = timezone.localtime(document.created)
subject = parse_w_workflow_placeholders(
action.email_subject,
action.email.subject,
correspondent,
document_type,
owner_username,
@ -902,7 +902,7 @@ def run_workflows(
doc_url,
)
body = parse_w_workflow_placeholders(
action.email_body,
action.email.body,
correspondent,
document_type,
owner_username,
@ -916,13 +916,13 @@ def run_workflows(
email = EmailMessage(
subject=subject,
body=body,
to=action.email_to.split(","),
to=action.email.to.split(","),
)
if action.email_include_document:
if action.email.include_document:
email.attach_file(document.source_path)
n_messages = email.send()
logger.debug(
f"Sent {n_messages} notification email(s) to {action.email_to}",
f"Sent {n_messages} notification email(s) to {action.email.to}",
extra={"group": logging_group},
)
except Exception as e:
@ -949,9 +949,9 @@ def run_workflows(
try:
data = {}
if action.webhook_use_params:
if action.webhook.use_params:
try:
for key, value in action.webhook_params.items():
for key, value in action.webhook.params.items():
data[key] = parse_w_workflow_placeholders(
value,
correspondent,
@ -970,7 +970,7 @@ def run_workflows(
)
else:
data = parse_w_workflow_placeholders(
action.webhook_body,
action.webhook.body,
correspondent,
document_type,
owner_username,
@ -981,30 +981,30 @@ def run_workflows(
doc_url,
)
headers = {}
if action.webhook_headers:
if action.webhook.headers:
try:
headers = {
str(k): str(v) for k, v in action.webhook_headers.items()
str(k): str(v) for k, v in action.webhook.headers.items()
}
except Exception as e:
logger.error(
f"Error occurred parsing webhook headers: {e}",
extra={"group": logging_group},
)
if action.webhook_include_document:
if action.webhook.include_document:
with open(document.source_path, "rb") as f:
files = {
"file": (document.original_filename, f, document.mime_type),
}
httpx.post(
action.webhook_url,
action.webhook.url,
data=data,
files=files,
headers=headers,
)
else:
httpx.post(
action.webhook_url,
action.webhook.url,
data=data,
headers=headers,
)

View File

@ -484,8 +484,10 @@ class TestApiWorkflows(DirectoriesMixin, APITestCase):
"actions": [
{
"type": WorkflowAction.WorkflowActionType.EMAIL,
"email_subject": "Subject",
"email_body": "Body",
"email": {
"subject": "Subject",
"body": "Body",
},
},
],
},
@ -511,9 +513,12 @@ class TestApiWorkflows(DirectoriesMixin, APITestCase):
"actions": [
{
"type": WorkflowAction.WorkflowActionType.EMAIL,
"email_subject": "Subject",
"email_body": "Body",
"email_to": "me@example.com",
"email": {
"subject": "Subject",
"body": "Body",
"to": "me@example.com",
"include_document": False,
},
},
],
},
@ -572,7 +577,10 @@ class TestApiWorkflows(DirectoriesMixin, APITestCase):
"actions": [
{
"type": WorkflowAction.WorkflowActionType.WEBHOOK,
"webhook_url": "https://example.com",
"webhook": {
"url": "https://example.com",
"include_document": False,
},
},
],
},

View File

@ -31,6 +31,8 @@ from documents.models import StoragePath
from documents.models import Tag
from documents.models import Workflow
from documents.models import WorkflowAction
from documents.models import WorkflowActionEmail
from documents.models import WorkflowActionWebhook
from documents.models import WorkflowRun
from documents.models import WorkflowTrigger
from documents.signals import document_consumption_finished
@ -2109,12 +2111,15 @@ class TestWorkflows(
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
email_action = WorkflowActionEmail.objects.create(
subject="Test Notification: {doc_title}",
body="Test message: {doc_url}",
to="user@example.com",
include_document=False,
)
action = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.EMAIL,
email_subject="Test Notification: {doc_title}",
email_body="Test message: {doc_url}",
email_to="user@example.com",
email_include_document=False,
email=email_action,
)
w = Workflow.objects.create(
name="Workflow 1",
@ -2161,12 +2166,15 @@ class TestWorkflows(
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
email_action = WorkflowActionEmail.objects.create(
subject="Test Notification: {doc_title}",
body="Test message: {doc_url}",
to="me@example.com",
include_document=True,
)
action = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.EMAIL,
email_subject="Test Notification: {doc_title}",
email_body="Test message: {doc_url}",
email_to="me@example.com",
email_include_document=True,
email=email_action,
)
w = Workflow.objects.create(
name="Workflow 1",
@ -2202,11 +2210,14 @@ class TestWorkflows(
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
email_action = WorkflowActionEmail.objects.create(
subject="Test Notification: {doc_title}",
body="Test message: {doc_url}",
to="me@example.com",
)
action = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.EMAIL,
email_subject="Test Notification: {doc_title}",
email_body="Test message: {doc_url}",
email_to="me@example.com",
email=email_action,
)
w = Workflow.objects.create(
name="Workflow 1",
@ -2247,11 +2258,14 @@ class TestWorkflows(
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
email_action = WorkflowActionEmail.objects.create(
subject="Test Notification: {doc_title}",
body="Test message: {doc_url}",
to="me@example.com",
)
action = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.EMAIL,
email_subject="Test Notification: {doc_title}",
email_body="Test message: {doc_url}",
email_to="me@example.com",
email=email_action,
)
w = Workflow.objects.create(
name="Workflow 1",
@ -2296,12 +2310,15 @@ class TestWorkflows(
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
webhook_action = WorkflowActionWebhook.objects.create(
use_params=False,
body="Test message: {doc_url}",
url="http://paperless-ngx.com",
include_document=False,
)
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,
webhook=webhook_action,
)
w = Workflow.objects.create(
name="Workflow 1",
@ -2348,12 +2365,15 @@ class TestWorkflows(
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
webhook_action = WorkflowActionWebhook.objects.create(
use_params=False,
body="Test message: {doc_url}",
url="http://paperless-ngx.com",
include_document=True,
)
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=True,
webhook=webhook_action,
)
w = Workflow.objects.create(
name="Workflow 1",
@ -2373,6 +2393,7 @@ class TestWorkflows(
correspondent=self.c,
original_filename="simple.pdf",
filename=test_file,
mime_type="application/pdf",
)
run_workflows(WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED, doc)
@ -2380,7 +2401,7 @@ class TestWorkflows(
mock_post.assert_called_once_with(
"http://paperless-ngx.com",
data=f"Test message: http://localhost:8000/documents/{doc.id}/",
files={"file": ("simple.pdf", mock.ANY)},
files={"file": ("simple.pdf", mock.ANY, "application/pdf")},
headers={},
)
@ -2402,15 +2423,18 @@ class TestWorkflows(
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
action = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.WEBHOOK,
webhook_use_params=True,
webhook_params={
webhook_action = WorkflowActionWebhook.objects.create(
use_params=True,
params={
"title": "Test webhook: {doc_title}",
"body": "Test message: {doc_url}",
},
webhook_url="http://paperless-ngx.com",
webhook_include_document=True,
url="http://paperless-ngx.com",
include_document=True,
)
action = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.WEBHOOK,
webhook=webhook_action,
)
w = Workflow.objects.create(
name="Workflow 1",
@ -2447,12 +2471,15 @@ class TestWorkflows(
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
webhook_action = WorkflowActionWebhook.objects.create(
url="http://paperless-ngx.com",
use_params=True,
params="invalid",
headers="invalid",
)
action = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.WEBHOOK,
webhook_url="http://paperless-ngx.com",
webhook_use_params=True,
webhook_params="invalid",
webhook_headers="invalid",
webhook=webhook_action,
)
w = Workflow.objects.create(
name="Workflow 1",