- Introduce a new API endpoint for counting subscribers matching a SQL snippet.
- Implement the HandleCountSQLSnippet function in the backend.
- Add frontend API call for counting SQL snippets with loading and error handling.
- Enhance SQL Snippets view with live validation and autocomplete for SQL snippets.
- Update navigation and UI elements for better user experience.
- Fix Exec() return value handling in UpdateSQLSnippet and DeleteSQLSnippet
- Add explicit BOOLEAN casting in get-sql-snippets query to resolve parameter type ambiguity
- Change config port from 9001 to 9000 to match documentation
- Add SQL snippets table and migration
- Create CRUD operations for managing reusable SQL query fragments
- Add frontend UI for SQL snippets management
- Include query validation and syntax highlighting
- Add navigation menu integration
- Requires subscribers:sql_query permission
This is the first part of a larger feature split from dynamic segments.
- 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.
This permission was never checked for and had an unintended consequence of
allowing a non-superadmin user to execute arbitrary queries (expected), but
getting a superadmin session by joining the `sessions` table.
This patch:
- Introduces a table allowlist that uses the Postgres query plan (JSON)
and validate the referenced tables against the allowed ones on arbitrary
queries issued to the various `/subscribers` APIs.
- Explicitly adds the missing `subscribers:sql_query` permission check to all
handlers that accept `query`.
- Introduces a new `search` parameter on all handlers that accept `query`.
This parameter is an interface over the default name/email substring search
instead of relying on `query`.
- During install, listmonk now accepts the env `LISTMONK_ADMIN_API_USER`
and creates an API user (with username $LISTMONK_ADMIN_API_USER)
with full superadmin permissions. This requires LISTMONK_ADMIN_USER and
LISTMONK_ADMIN_API_PASSWORD to be set so that that there's always a superadmin
user to avoid bad states, mainly: bot superadmin exists, but no admin user
exists, leaving the installation perpetually open with the superadmin user
creation UI on the first login.
The API user's token is printed to stderr in the following format:
`export LISTMONK_ADMIN_API_TOKEN="7I81VSd90UWhKDj5Kq9c6YopToRduyDF"`
This can be redirected to a file with ./listmonk 2> /tmp/token or captured
directly and then source()'d.
- Add new function `core.GetRole(id)`.
- Fix `at least one super admin` query in user deletion.
- Make the beginning of handlers consistent with uniform variable declaration
and grouping.
- Add missing comments.
- Fix staticcheck/vet warnings and idiom issues.
- 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.
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.
- Fix status/button state management issues when `Send at` was toggled
under various scenarios.
- Allow paused campaigns to be edited and turned into scheduled campaigns.
- Add Cypress UI tests for unscheduling.
This patch removes the forced suffixing of all media upload filenames with
random strings. The upload handler now checks the `media` table to ensure that
the filename being uploaded doesn't exist before forcing a suffix.
Outright rejecting duplicate filenames cannot be done to maintain backwards
compatibility with the old behaviour.
Closes#2277.
This commit splits roles into two, user roles and list roles, both of which
are attached separately to a user.
List roles are collection of lists each with read|write permissions, while
user roles now have all permissions except for per-list ones.
This allows for easier management of roles, eliminating the need to clone and
create new roles just to adjust specific list permissions.
- Filter lists by permitted list IDs in DB get calls.
- Split getLists() handlers into two (one, all) for clarity.
- Introduce new `subscribers:get_by_list` permission.
- Tweak UI rendering to work with new per-list permssions.
- Add materialized views for list -> subscriber counts, dashboard chart,
and dashboard aggregate stats that slow down significantly on large
databases (with millions or tens of millions of subscribers). These
slow queries involve full table scan COUNTS().
- Add a toggle to enable caching slow results in Settings -> Performance.
- Add support for setting a cron string that crons and periodically
refreshes aggregated stats in materialized views.
Closes#1019.