Skip to content

Commit 5630586

Browse files
committed
!wip
1 parent 8bc60b5 commit 5630586

40 files changed

+2859
-168
lines changed

src/backend/core/api/openapi.json

Lines changed: 457 additions & 0 deletions
Large diffs are not rendered by default.

src/backend/core/api/viewsets/message_template.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ def get_queryset_for_list(self):
9393
queryset = MessageTemplate.objects.all()
9494
elif mailbox_id:
9595
accessible_mailboxes = Mailbox.objects.filter(accesses__user=user)
96+
accessible_maildomains = MailDomain.objects.filter(Q(accesses__user=user) | Q(mailbox__in=accessible_mailboxes))
9697
queryset = MessageTemplate.objects.filter(
9798
template_mailboxes__mailbox_id__in=accessible_mailboxes
9899
)
@@ -105,11 +106,16 @@ def get_queryset_for_list(self):
105106
is_default = self.request.query_params.get("is_default")
106107
# filter by mailbox_id or maildomain_id
107108
if mailbox_id:
108-
queryset = queryset.filter(template_mailboxes__mailbox_id=mailbox_id)
109+
mailbox = Mailbox.objects.get(id=mailbox_id)
110+
queryset = queryset.filter(
111+
Q(template_mailboxes__mailbox_id=mailbox_id)
112+
| Q(template_maildomains__maildomain_id=mailbox.domain)
113+
)
109114
if is_default is not None:
110115
is_default_bool = is_default.lower() in ("true", "1", "yes")
111116
queryset = queryset.filter(
112-
template_mailboxes__is_default=is_default_bool
117+
Q(template_mailboxes__is_default=is_default_bool)
118+
| Q(template_maildomains__is_default=is_default_bool)
113119
)
114120
if maildomain_id:
115121
queryset = queryset.filter(
@@ -174,6 +180,7 @@ def render_template(self, request, pk=None): # pylint: disable=unused-argument
174180
context = {
175181
"mailbox": str(mailbox),
176182
"fullname": user.full_name,
183+
"email": user.email,
177184
}
178185
try:
179186
rendered = template.render_template(context)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<<<<<<<< Updated upstream:src/backend/core/migrations/0006_messagetemplate_alter_maildomain_custom_attributes_and_more.py
2+
# Generated by Django 5.1.8 on 2025-08-20 06:48
3+
========
4+
# Generated by Django 5.1.8 on 2025-08-07 09:27
5+
>>>>>>>> Stashed changes:src/backend/core/migrations/0005_messagetemplate_alter_maildomain_custom_attributes_and_more.py
6+
7+
import django.db.models.deletion
8+
import uuid
9+
from django.db import migrations, models
10+
11+
12+
class Migration(migrations.Migration):
13+
14+
dependencies = [
15+
('core', '0005_label_description_label_is_auto_and_more'),
16+
]
17+
18+
operations = [
19+
migrations.CreateModel(
20+
name='MessageTemplate',
21+
fields=[
22+
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='primary key for the record as UUID', primary_key=True, serialize=False, verbose_name='id')),
23+
('created_at', models.DateTimeField(auto_now_add=True, help_text='date and time at which a record was created', verbose_name='created on')),
24+
('updated_at', models.DateTimeField(auto_now=True, help_text='date and time at which a record was last updated', verbose_name='updated on')),
25+
('name', models.CharField(help_text="Name of the template (e.g., 'Standard Reply', 'Out of Office', 'Work Signature')", max_length=255, verbose_name='name')),
26+
('description', models.TextField(blank=True, help_text='Optional description of when to use this template', verbose_name='description')),
27+
('html_body', models.TextField(blank=True, help_text="HTML email body template with placeholders (e.g., '<p>Dear {recipient_name},</p>') or signature content", verbose_name='HTML body')),
28+
('text_body', models.TextField(blank=True, help_text="Plain text email body template with placeholders (e.g., 'Dear {recipient_name},') or signature content", verbose_name='text body')),
29+
<<<<<<<< Updated upstream:src/backend/core/migrations/0006_messagetemplate_alter_maildomain_custom_attributes_and_more.py
30+
('kind', models.SmallIntegerField(choices=[(1, 'reply'), (2, 'new_message'), (3, 'signature')], default=1, help_text='Kind of template (reply, forward, new message, auto reply, signature)', verbose_name='kind')),
31+
========
32+
('kind', models.SmallIntegerField(choices=[(1, 'reply'), (2, 'forward'), (3, 'new_message'), (4, 'auto_reply'), (5, 'signature')], default=1, help_text='Kind of template (reply, forward, new message, auto reply, signature)', verbose_name='kind')),
33+
>>>>>>>> Stashed changes:src/backend/core/migrations/0005_messagetemplate_alter_maildomain_custom_attributes_and_more.py
34+
('is_active', models.BooleanField(default=True, help_text='Whether this template is available for use', verbose_name='is active')),
35+
],
36+
options={
37+
'verbose_name': 'message template',
38+
'verbose_name_plural': 'message templates',
39+
'db_table': 'messages_messagetemplate',
40+
'ordering': ['name'],
41+
},
42+
),
43+
migrations.AlterField(
44+
model_name='maildomain',
45+
name='custom_attributes',
46+
field=models.JSONField(blank=True, default=dict, help_text='Metadata to sync to the maildomain group in the identity provider.', verbose_name='Custom attributes'),
47+
),
48+
migrations.AlterField(
49+
model_name='user',
50+
name='custom_attributes',
51+
field=models.JSONField(blank=True, default=dict, help_text='Metadata to sync to the user in the identity provider.', verbose_name='Custom attributes'),
52+
),
53+
migrations.CreateModel(
54+
name='MessageTemplateMailbox',
55+
fields=[
56+
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='primary key for the record as UUID', primary_key=True, serialize=False, verbose_name='id')),
57+
('created_at', models.DateTimeField(auto_now_add=True, help_text='date and time at which a record was created', verbose_name='created on')),
58+
('updated_at', models.DateTimeField(auto_now=True, help_text='date and time at which a record was last updated', verbose_name='updated on')),
59+
('is_default', models.BooleanField(default=False, help_text='Whether this template is the default for this mailbox', verbose_name='is default')),
60+
('mailbox', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='template_mailboxes', to='core.mailbox')),
61+
('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='template_mailboxes', to='core.messagetemplate')),
62+
],
63+
options={
64+
'verbose_name': 'message template mailbox',
65+
'verbose_name_plural': 'message template mailboxes',
66+
'db_table': 'messages_messagetemplatemailbox',
67+
'unique_together': {('template', 'mailbox')},
68+
},
69+
),
70+
migrations.AddField(
71+
model_name='messagetemplate',
72+
name='mailboxes',
73+
field=models.ManyToManyField(help_text='Mailboxes that can use this template', related_name='message_templates', through='core.MessageTemplateMailbox', to='core.mailbox'),
74+
),
75+
migrations.CreateModel(
76+
name='MessageTemplateMailDomain',
77+
fields=[
78+
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='primary key for the record as UUID', primary_key=True, serialize=False, verbose_name='id')),
79+
('created_at', models.DateTimeField(auto_now_add=True, help_text='date and time at which a record was created', verbose_name='created on')),
80+
('updated_at', models.DateTimeField(auto_now=True, help_text='date and time at which a record was last updated', verbose_name='updated on')),
81+
('is_default', models.BooleanField(default=False, help_text='Whether this template is the default for this mail domain', verbose_name='is default')),
82+
('maildomain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='template_maildomains', to='core.maildomain')),
83+
('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='template_maildomains', to='core.messagetemplate')),
84+
],
85+
options={
86+
'verbose_name': 'message template mail domain',
87+
'verbose_name_plural': 'message template mail domains',
88+
'db_table': 'messages_messagetemplatemaildomain',
89+
'unique_together': {('template', 'maildomain')},
90+
},
91+
),
92+
migrations.AddField(
93+
model_name='messagetemplate',
94+
name='maildomains',
95+
field=models.ManyToManyField(help_text='Mail domains that can use this template', related_name='message_templates', through='core.MessageTemplateMailDomain', to='core.maildomain'),
96+
),
97+
]

src/backend/core/migrations/0006_messagetemplate_alter_maildomain_custom_attributes_and_more.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
<<<<<<<< Updated upstream:src/backend/core/migrations/0006_messagetemplate_alter_maildomain_custom_attributes_and_more.py
12
# Generated by Django 5.1.8 on 2025-08-20 06:48
3+
========
4+
# Generated by Django 5.1.8 on 2025-08-07 09:27
5+
>>>>>>>> Stashed changes:src/backend/core/migrations/0005_messagetemplate_alter_maildomain_custom_attributes_and_more.py
26

37
import django.db.models.deletion
48
import uuid
@@ -22,7 +26,11 @@ class Migration(migrations.Migration):
2226
('description', models.TextField(blank=True, help_text='Optional description of when to use this template', verbose_name='description')),
2327
('html_body', models.TextField(blank=True, help_text="HTML email body template with placeholders (e.g., '<p>Dear {recipient_name},</p>') or signature content", verbose_name='HTML body')),
2428
('text_body', models.TextField(blank=True, help_text="Plain text email body template with placeholders (e.g., 'Dear {recipient_name},') or signature content", verbose_name='text body')),
29+
<<<<<<<< Updated upstream:src/backend/core/migrations/0006_messagetemplate_alter_maildomain_custom_attributes_and_more.py
2530
('kind', models.SmallIntegerField(choices=[(1, 'reply'), (2, 'new_message'), (3, 'signature')], default=1, help_text='Kind of template (reply, forward, new message, auto reply, signature)', verbose_name='kind')),
31+
========
32+
('kind', models.SmallIntegerField(choices=[(1, 'reply'), (2, 'forward'), (3, 'new_message'), (4, 'auto_reply'), (5, 'signature')], default=1, help_text='Kind of template (reply, forward, new message, auto reply, signature)', verbose_name='kind')),
33+
>>>>>>>> Stashed changes:src/backend/core/migrations/0005_messagetemplate_alter_maildomain_custom_attributes_and_more.py
2634
('is_active', models.BooleanField(default=True, help_text='Whether this template is available for use', verbose_name='is active')),
2735
],
2836
options={

src/frontend/src/features/api/gen/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export * from "./mailboxes/mailboxes";
99
export * from "./mailbox-accesses/mailbox-accesses";
1010
export * from "./maildomains/maildomains";
1111
export * from "./admin-maildomain-user/admin-maildomain-user";
12+
export * from "./message-templates/message-templates";
1213
export * from "./mta/mta";
1314
export * from "./placeholders/placeholders";
1415
export * from "./tasks/tasks";

0 commit comments

Comments
 (0)