Commit graph

59 commits

Author SHA1 Message Date
Kailash Nadh
47e8f8164f Default body_source to null instead of empty string in non-visual campaigns. 2025-04-28 22:56:59 +05:30
Kailash Nadh
ed700d7a33 Add a Preview option to the campaign archive tab. Closes #2245. 2025-04-21 18:17:46 +05:30
Kailash Nadh
20e4b100ca Fix DB state issues in visual campaign cloning. 2025-04-20 20:48:51 +05:30
Kailash Nadh
f1fbadf6a6 Fix incorrect template states in DB in campaign creation and broken preview. 2025-04-20 20:48:51 +05:30
Kailash Nadh
c1f81cfadd Fix compatibility issues with master.
- Fix merge conflicts.
- Simply logic in campaign preview handler.
- Remove redundant `GetCampaignForPreviewWithTemplate()` and switch to the old
  query that optionally takes a template.
- Fix Vue linting issues.
2025-04-20 20:48:51 +05:30
Kailash Nadh
0826f401b7 Remove repetitive URL param :id validation and simplify handlers.
This patch significantly cleans up clunky, repetitive, and pervasive
validation logic across HTTP handlers.

- Rather than dozens of handlers checking and using strconv to validate ID,
  the handlers with `:id` are now wrapped in a `hasID()` middleware that does
  the validation and sets an int `id` in the handler context that the wrapped
  handlers can now access with `getID()`.

- Handlers that handled both single + multi resource requests
  (eg: GET `/api/lists`) with single/multiple id checking conditions are all now
  split into separate handlers, eg: `getList()`, `getLists()`.
2025-04-06 14:01:21 +05:30
Kailash Nadh
78366ab7e4 Clean up main initialization to remove app interdepencies in init.
`App{}` now is used purely as a container for HTTP handlers.
2025-04-06 00:28:35 +05:30
Kailash Nadh
88489223c9 Remove superfluous consts dep in init functions by separating URL consts. 2025-04-05 23:39:08 +05:30
Kailash Nadh
e2f24a140e Turn notifs into a special stateful global singleton package, removing clunky deps. 2025-04-05 22:45:19 +05:30
Kailash Nadh
e327ebbbdf Move all HTTP handlers directly to App and remove the redundant in-between layer. 2025-04-05 19:24:25 +05:30
Kailash Nadh
b3d46a8c85 Refactor system notification callbacks into a new notifs package. 2025-04-05 19:07:06 +05:30
Kailash Nadh
00c858fc49 Refactor all HTTP handlers and attach them to a single struct.
- Attach all HTTP handlers to a new `Handlers{}` struct.
- Remove all `handle*` function prefixes.
- Remove awkward, repetitive `app = c.Get("app").(*App)` from all handlers
  and instead, simply access it from `h.app` from `Handlers{}`

Originally proposed in #2292.
2025-04-05 15:42:35 +05:30
Kailash Nadh
007f4de850 Fix a number of cosmetic inconsistenies across handlers and functions.
- Make the beginning of handlers consistent with uniform variable declaration
  and grouping.
- Add missing comments.
- Fix staticcheck/vet warnings and idiom issues.
2025-04-05 13:41:31 +05:30
Kailash Nadh
fcf2449a70 Replace awkward auth user object access in handlers with an explicit func. 2025-04-05 00:26:05 +05:30
Kailash Nadh
17998fbff5 Refactor user auth models and permission checks.
- Move user models from `/models` to `internal/auth`.
- Move and refactor various permission check functions into `User.()`
- Refactor awkward `get, manage bool` function args into `Get|Manage` bitflags.
2025-04-05 00:19:27 +05:30
Kailash Nadh
a271bf54d5 Introduce per-campaign filter permissions. Closes #2325.
This patch introduces new `campaigns:get_all` and `campaigns:manage_all`
permissions which alter the behaviour of the the old `campaigns:get` and
`campaigns:manage` permissions. This is a subtle breaking behavioural change.

Old:

- `campaigns:get` -> View all campaigns irrespective of a user's list
  permissions.
- `campaigns:manage` -> Manage all campaigns irrespective of a user's list
  permissions.

New:

- `campaigns:get_all` -> View all campaigns irrespective of a user's list
  permissions.
- `campaigns:manage_all` -> Manage all campaigns irrespective of a user's list
  permissions.
- `campaigns:get` -> View only the campaigns that have at least one list to
  which which a user has get or manage access.
- `campaigns:manage` -> Manage only the campaigns that have at list one list
  to which a user has get or manage access.

In addition, this patch refactors and cleans up certain permission related
logic and functions.
2025-03-31 16:39:42 +05:30
Kailash Nadh
3d383cd537 Make paused campaigns editable. 2025-01-19 16:40:25 +05:30
Kailash Nadh
fd31ac6f58 Remove redundant send_later param in campaign POST/PUT. 2025-01-19 16:06:39 +05:30
Kailash Nadh
c2e7c713ca Increase campaign subject char limit. Closes #1909. 2024-07-17 19:38:11 +05:30
Kailash Nadh
86771512ce Merge branch 'slug' 2024-01-09 23:34:25 +05:30
Kailash Nadh
0d319ad9fd Add 'slug' (permalink) support for campaign archives. Closes #1394. 2024-01-09 23:34:08 +05:30
mpilnan
78caa35e42
fix: add copying campaign object before sending test message (#1659) 2024-01-09 23:22:01 +05:30
Kailash Nadh
414c5c0c99 Refactor the core concurrent campaign manager logic.
This commit fully refactors the core campaign manager logic.
It applies a whole new approach to campaign state and lifecycle management.

- Create a new "pipeline" abstraction on top of campaign
  for state management.
- Account for every message processed and end campaigns
  based on the actual count.
- Discard in-queue messages in the pipeline of a paused
  or cancelled campaign.
2024-01-02 14:57:04 +05:30
Kailash Nadh
2feb1b0fb8 Make the name part in from e-mails optional. Closes #1602. 2023-12-30 21:48:12 +05:30
Kailash Nadh
01acd386f6 Add tag/type/optin filter options to lists and campaigns APIs. Closes #1631. 2023-12-23 14:45:55 +05:30
Kailash Nadh
2215511f2c Increase the arbitrarily low max-input-length limit. Closes #1416. 2023-08-03 23:52:20 +05:30
Kailash Nadh
3b9a0f782e
Add support for file attachments on campaigns (#1341)
- Adds support for arbitrary file uploads with an admin setting to select allowed file extensions.
- Adds support for attaching media (files) to campaigns.
2023-05-18 16:55:59 +05:30
Kailash Nadh
56a9836e86 Integrate paginator library in place of custom pagination function. 2022-11-10 23:30:50 +05:30
Kailash Nadh
9add728b08 WIP: Add support for publishing campaigns to publish archives. 2022-11-10 23:30:11 +05:30
Kailash Nadh
d2ef23d3fa Refactor paginated campaign query function to return DB total. 2022-05-03 10:50:33 +05:30
Kailash Nadh
b5cd9498b1 Refactore all CRUD functions to a new core package.
This is a long pending refactor. All the DB, query, CRUD, and related
logic scattered across HTTP handlers are now moved into a central
`core` package with clean, abstracted methods, decoupling HTTP
handlers from executing direct DB queries and other business logic.

eg: `core.CreateList()`, `core.GetLists()` etc.

- Remove obsolete subscriber methods.
- Move optin hook queries to core.
- Move campaign methods to `core`.
- Move all campaign methods to `core`.
- Move public page functions to `core`.
- Move all template functions to `core`.
- Move media and settings function to `core`.
- Move handler middleware functions to `core`.
- Move all bounce functions to `core`.
- Move all dashboard functions to `core`.
- Fix GetLists() not honouring type
- Fix unwrapped JSON responses.
- Clean up obsolete pre-core util function.
- Replace SQL array null check with cardinality check.
- Fix missing validations in `core` queries.
- Remove superfluous deps on internal `subimporter`.
- Add dashboard functions to `core`.
- Fix broken domain ban check.
- Fix broken subscriber check middleware.
- Remove redundant error handling.
- Remove obsolete functions.
- Remove obsolete structs.
- Remove obsolete queries and DB functions.
- Document the `core` package.
2022-05-03 10:50:29 +05:30
Gokul Menon
04c4552a9c Fixed typos 2022-02-28 14:19:50 +01:00
Yatish Mehta
6c903239dd Fix typos 2022-02-13 08:54:39 -08:00
Kailash Nadh
0f6a0376da Add accurate realtime message rate counter.
The `rate` field `/api/campaigns/running/stats` returned was computed
based on the total time spent from the start of the campaign to the
current time. This meant that for large campaigns, if there were
pauses or slowdowns in between, the rate would be skewed heavily
making it useless to figure out the current send rate.

This commit introduces a realtime running rate counter in the campaign
manager that returns accurate (running) send rates for the last minute.

The `rate` field in the API now shows the live running rate and a
new `net_rate` field shows the rate from the beginning of the campaign.
2022-02-06 11:38:02 +05:30
Kailash Nadh
583dab4bc6 Add support for per-campaign custom headers.
- Add new `headers[]` column to the campain table.
- Add new headers box to the campaign UI that takes a JSON array of
  custom headers like the headers on the SMTP settings UI.
- Headers are added to e-mails and messenger postback webhooks.
- Add cypress tests.

Closes #514.
2022-01-04 22:27:40 +05:30
Kailash Nadh
ca128df49a Add support for searching lists + search UI. Closes #618. 2021-12-09 21:34:38 +05:30
Kailash Nadh
e9709e54ee Upgrade labstack/echo webserver to major version v4.
- echo is now on v4 with major changes including a few breaking changes
- bind() behaviour is now strict. JSON / form etc. unmarshalling of
  request data need appropriate `json`, `form` tags. Missing tags for
  the public subscription page is added in this commit.
- This also closes #602.
2021-12-09 20:51:07 +05:30
Kailash Nadh
c8c135e31f Fix broken test mail due to missing tpl param. 2021-11-10 20:47:55 +05:30
Kailash Nadh
0bd13fe541 Fix response content type in plaintext campaign previews. Closes #568 2021-11-05 09:21:39 +05:30
Kailash Nadh
5bfbe15c24 Fix campaign template preview not working without saving. Closes #553. 2021-10-31 11:49:43 +05:30
Kailash Nadh
b290d271c0 Add support for plaintext system e-mail templates.
If `<!doctype html>` is not found in static/email-templates/base.html,
all system e-mail templates are assumed to be plaintext and go out
as content-type: plaintext e-mails. With this, all HTML tags can
be stripped out of the system e-mail templates (while maintaining
Go template tags and logic) to have plaintext system e-mail templates.

Closes #546
2021-10-28 20:09:06 +05:30
Kailash Nadh
4056187fec Add sane defaults to POST creation APIs. 2021-09-26 16:43:10 +05:30
Kailash Nadh
7aee36eab1 Add support for blocklisting e-mail domains.
E-mails in the domain blocklist are disallowed on the admin UI, public
subscription forms, API, and in the bulk importer.

- Add blocklist setting that takes a list of multi-line domains on the
  Settings -> Privacy UI.
- Refactor e-mail validation in subimporter to add blocklist checking
  centrally.
- Add Cypress testr testing domain blocklist behaviour on admin
  and non-admin views.

Closes #336.
2021-09-25 15:39:09 +05:30
Kailash Nadh
61e88681ed Add campaign analytics APIs and UI 2021-09-17 21:41:25 +05:30
Kailash Nadh
1ae98699e7 Add support for bounce processing.
- Blocklist or unsubscribe subscribers based on a bounce threshold
- Add /bounces UI for viewing bounces and in the subscriber view
- Add settings UI for managing bounce settings
- Add support for scanning POP3 bounce mailboxes
- Add a generic webhook for posting custom bounces at /webhooks/bounce
- Add SES bounce webhook support at /webhooks/services/ses
- Add Sendgrid bounce webhook support at /webhooks/services/sendgrid
2021-08-14 15:35:29 +05:30
Kailash Nadh
8859911c73 Remove hardcoded limit for per_page in pagination 2021-06-05 12:01:33 +05:30
Kailash Nadh
931e467b25 Fixes campaign test messages not including unsub headers.
Campaign messages are handled by `manager` whereas test messages
were being pushed directly into a messenger skipping some campaign
related routines such as the addition of list unsub headers.

This commit exposes a new function `manager.PushCampaignMessage()`
that accepts arbitrary campaign messages that then pass through
the standard campaign message workers, thus getting the missing unsub
headers. This closes #360.

In addition, this removes the superfluous `CampaignMessage.Render()`
function which had to be mandatorily called always and makes it
implicit in `manager.NewCampaignMessage()`.
2021-05-21 23:35:08 +05:30
Kailash Nadh
65d25fc3f9 Improve campaign content format conversion.
Previously, converting between formats simply copied over raw content.
This update does actual conversion between different formats. While
lossy, this seems to a good enough approximation for even reasonbly
rich HTML content. Closes #348.

- richtext, html => plain
  Strips HTML and converts content to plain text.

- richtext, html => markdown
  Uses turndown (JS) lib to convert HTML to Markdown.

- plain => richtext, html
  Converts line breaks in plain text to HTML breaks.

- richtext => html
  "Beautifies" the HTML generated by the WYSIWYG editor unlike the
  earlier behaviour of dumping one long line of HTML.

- markdown => richtext, html
  Makes an API call to the backend to use the Goldmark lib to convert
  Markdown to HTML.
2021-05-09 15:36:31 +05:30
Kailash Nadh
37824136c0 Refactor campaign preview to use dummy campaign and subscriber.
Use a dummy subscriber instead of fetching a random one from the
DB. In addition, replace the preview campaign UUID with a dummy
one to prevent clicks and views being registered against the
campaign when previewing.
2021-04-21 15:32:05 +05:30
Kailash Nadh
1e59d53135 Add markdown support to campaign content. 2021-04-14 12:26:09 +05:30