What's changed
Features (16)
-
admin: add inactive user filter in Django admin user list (#6367)
Adds a new Inactive users filter in the Django admin user list, allowing
superusers to quickly find accounts that have been inactive for 90, 180,
365, or 730 days.This update introduces an
Inactive ≥ X days
preset filter in the admin
user list.
The filter leverages the existing inactivity detection logic
(get_inactive_users()
) to identify users who haven’t logged in or
shown activity within the selected time frame. -
api: add basic HTML renderer to API endpoints (#6320)
Provide a lightweight HTML view for API responses with a direct link to
the new documentation filtered on the endpoint URL. -
assetVersions: remove reversion version foreign key (#6157)
-
background-audio-recording: modify messages about bg audio recording on form builder (#6185)
This PR modifies messages about the capabilities of background audio
recording present in the form builder.
[See requirements in Linear task](https://linear.app/kobotoolbox/issue//changeremove-background-audio-availability-warning)
-
components: add tooltips to icon only buttons with storybook option (#6123)
Adds ability for tooltips to be used with icon only buttons. Useful for
some UI designs -
dataCollectors: set up initial models and admin (#6142)
Add new data collector models to Django admin.
Adds DataCollector and DataCollectorGroup models to Django admin. A
DataCollectorGroup may have several DataCollectors and be associated
with several Assets. Every DataCollector has a token, which may be
rotated using Django admin. -
dataCollectors: utilities for creating enketo links (#6196)
-
dataCollectors: update enketo links when assigning assets to groups (#6197)
Create/update enketo links for data collectors when assigning assets to
data collector groups.Create the necessary enketo links for data collectors so they can
view/submit to the assets to which their group has access. -
dataCollectors: create authentication class for data collectors (#6203)
-
instanceHistory: add root_uuid to instancehistory (#6143)
-
instanceHistory: Celery task to clean instance history records (#6165)
InstanceHistory objects are kept for an amount of days given by the
constance parameter SUBMISSION_HISTORY_GRACE_PERIOD. After this period
has passed, the records that have no associated instance (xform_instance
= NULL) are deleted by a celery task that runs weekly. -
massEmails: get name from extra details (#6131)
Use the user-entered name in mass email templates.
-
permissions: Kobocat/OpenRosa - Merge Permissions Systems (#5887)
This contains multiple PR's from the project
Kobocat/OpenRosa - Merge Permissions Systems
:- Remove the ObjectPermissionBackend
- Remove Guardian related code
- Clean up obsolete Kobocat/OpenRosa permissions code
- Remove all occurrences of the special permission PERM_FROM_KC_ONLY from the database and from the codebase
- Remove Guardian dependancy.
- Replacing guardian extension used in openrosa apps with functions from the kpi permissions system.
-
permissions: use new endpoint for bulk removing (#6358)
Use new endpoint for removing all user permissions.
-
reversion: task to remove version objects (#6162)
-
reversion: optimize version removal task (#6204)
Bug Fixes (33)
-
UniversalTable: don't crash while data is loading (#6141)
-
UniversalTable: don't crash in webpack (#6147)
-
admin: add admin action to bulk mark selected users as inactive (#6381)
Adds a new admin action in the Django user list allowing superusers to
bulk mark selected users as inactive.This update introduces a bulk action in the Django admin's
Users
page
that lets superusers quickly mark multiple accounts as inactive.
The action is designed to complement the existing inactive users filter,
after filtering inactive accounts (e.g., inactive for > 90 days),
superusers can now select them and deactivate all in one step. -
api: restore default renderers for API
v1
(#6257)Reinstate API v1’s renderer settings so browsers receive HTML by default
instead of XML. -
api: respect the rendering format when it is provided (#6325)
Remove custom negotiation class which broke the rendering of the API
response with a browser -
api: correct
uid
value for asset snapshot manifest endpoint (#6351)Fix
uid
value that was missed in #6323 resulting in form previews and
submission edits failures. -
api: align detail action parameters with URL patterns (#6382)
Ensure detail action method signatures use the correct parameter names
defined in their URL patterns. -
assets: fix infinite load when previewing form as anonymous user (#6336)
Fixes an issue where publicly shared forms failed to load when viewed by
an anonymous user. Anonymous form previews now open correctly without
infinite loading.Previously, when a project owner shared a form publicly ("Anyone can
view this form") and an anonymous user tried to preview it, the page
would load indefinitely.
This happened because the backendasset_snapshots
API returned a401 Authentication credentials were not provided
error when anonymous users
attempted to create a snapshot for form preview.This PR updates the permission logic to allow anonymous snapshot
creation for publicly shared forms while still enforcing proper
object-level permissions and password protection.
As a result, public (anonymous) form previews now work as expected, with
no regressions for authenticated users or private assets. -
attachmentTrash: fix cleanup of orphaned
AttachmentTrash
andPeriodicTasks
(#6275)Fixed an issue where deleted submissions left behind orphaned attachment
trash records and their associated periodic tasks.Previously, if a submission was deleted after its attachments were moved
to the trash, the Admin still displayed those attachments in the trash
bin. Opening them caused errors, and their cleanup periodic tasks were
never removed. This update ensures that attachment trash entries and
their periodic tasks are correctly removed when the related submission
or attachment is deleted. A new management command also cleans up any
leftover broken records from the past. -
audioRecording: background audio file being soft deleted on creation (#6207)
This PR adds the pattern for the background audio file generated by
Enketo to the fix to avoid it being soft-deleted on creation -
billing: schedule update-exceeded-limit-counters with crontab (#6232)
Use crontab scheduling instead of timedelta for
update-exceeded-limit-counters task. -
billing: enforce grace period using
datetime
on exceeded limit counters (#6255)Fixed an issue where storage limit counters could update too early
because only the calendar date was checked. Now the system respects a
full 24-hour grace period before updating counters.Previously, exceeded limit counters were filtered using only the date
portion ofdate_modified
. This meant that if a user exceeded their
limit late in the day (e.g., 3 PM), the counter could be updated just
after midnight instead of waiting the full 24 hours.
We now compare the fulldatetime
so counters are only updated once the
full grace period has passed. This ensures fairer enforcement of storage
limits and avoids premature counter increments or deletions. -
dataCollectors: revert accidental change (#6154)
-
exports: simplify account log export prompt (#6183)
Notifications for exporting access logs now match notifications for
project activity logs -
exports: use empty object for empty payload (#6201)
-
fetch: headers handling on frontend API calls (#6211)
Fixes a bug with headers handling in recently refactored code for
frontend API calls that was causing an infinite loading spinner on the
usage page. -
frontend: ensure country list respects RTL languages (#5875)
Ensure countries list is displayed in the correct direction for RTL
languages.This adjusts
getCountryDisplayString
so that when the UI language is
RTL (like Arabic or Hebrew), the countries list respects the reading
order, improving the UX for RTL users.No functional changes outside the display of the countries string.
-
imports: revert
uid_import
property in import endpoint response (#6372) -
instanceHistory: Persist instance history when instance is deleted (#6152)
The InstanceHistory objects are not deleted when the referenced instance
is deleted anymore. They remain for an configurable amount of days after
which they are collected and purged -
languageSelector: remove native cancel button on chrome (#6202)
Chrome no longer displays two clear search buttons ("x") in Language
Selector component. -
massEmails: get name from user extra_details with no backup (#6163)
Use the full user name in the user extra_details object, for mass email
templates. If the user has no name it defaults to None.👀 Preview steps
This is most easily tested with MASS_EMAILS_CONDENSE_SEND set to true.
- Using a user account, add a full name in Account Settings
- Add the user's email to Constance > MASS_EMAIL_TEST_EMAILS
- Create a new mass email config using the test_users query that uses
##full_name## somewhere in the template and set it to live - 🟢 At the next email send, the name entered in the account settings
should be rendered in the email
-
migrations: partially revert #6157; avoid renaming
_reversion_version
(#6229) -
migrations: revert _reversion_version change in historical kpi 0015 migration (#6239)
-
nlp: reset polling status after auto translation finishes (#6184)
Fixes a bug in NLP where attempting a second automatic translation
resulted in a infinite loading screen -
permissions: exclude inactive users from permission assignment lists (#6329)
Hide inactive accounts from user pickers and API results when assigning
permissions. -
permissions: ensure complete removal of all user permissions (no cascade reliance) (#6324)
Replace cascade-based deletion that missed certain permissions (e.g.,
add_submissions
) with an explicit, comprehensive revoke process. -
permissions: prevent granting permissions to inactive users (#6330)
Stop assigning any permissions to users whose accounts are inactive.
-
permissions: drop guardian constraints (#6363)
-
permissions: [breaking] fix mistake in long running job that deletes obsolete permissions (#6370)
-
projectSettings: unnecessary modal padding (#6138)
-
releases: GHA order and syntax for checkout (#6378)
-
swaggerUI: restore search bar functionality with collapsed tags (#6319)
Fix Swagger UI search so results appear even when endpoint groups are collapsed by default.
-
tooltip: replace deprecated button with new button in table cells (#6178)
Replaces deprecated button with new button that fixes a tooltip issue in
the data table
Documentation (3)
-
accesslog: add proper markdown documentation for access logs (#6274)
Fix API documentation so the access log endpoints display their own
description instead of reusing audit log text.The API documentation for access logs was incorrectly showing the audit
log description because the access log view extends the audit log
viewset and inherited its markdown. This change introduces dedicated
markdown documentation for the access log endpoints, ensuring that their
purpose, fields, and usage are clearly documented and no longer
overwritten by audit log content. -
api: set up API documentation with drf-spectacular and Swagger UI (#5746)
Integrated drf-spectacular and Swagger UI to auto-generate OpenAPI
documentation and added developer documentation to guide implementation
for each endpoint.This PR introduces API documentation support using drf-spectacular for
OpenAPI schema generation and Swagger UI for live documentation
browsing. The setup enables automatic schema generation for KPI’s v2 API
and lays the foundation for documenting all endpoints consistently.Enabled Swagger UI at
/api/v2/docs/
and schema access at
/api/v2/schema/
. -
openApi: use separate settings for each API schema (#6371)
Apply distinct tag groups and descriptions when generating schemas for
API v2 and the OpenRosa API.
Continous Integration (13)
- npm: assert up to date package-lock.json (#6317)
- releases: release every 4 weeks (#6189)
- releases: release every 4 weeks, modulo 1 (#6208)
- releases: output a forgotten variable (#6212)
- releases: run version even if a test fails (#6316)
- releases: don't spam non-release branches (#6332)
- releases: more elaborate zulip notifications (#6360)
- releases: extract checkout-with-github-app-token (#6374)
- releases: handle secrets within composite actions (#6379)
- releases: push to beta cascades deploy (#6375)
- staging: deploy nonprod envs with github actions INFRA-14 (#6186)
- staging: Removing staging deploys from gitlab (#6220)
- storybook: Deploying storybook with GHA INFRA-15 (#6221)
Testing (1)
- fuzzyInt: update tests to match new expected query counts after recent changes (#6353)
Adjust fuzzy integer query count assertions to align with the updated
number of queries introduced in the latest release.
Security (12)
- deps: bump @tanstack/react-query from 5.84.1 to 5.85.5 (#6174)
- deps-dev: bump @storybook/addon-links from 9.0.0-beta.11 to 9.1.3 (#6148)
- deps-dev: bump @eslint/eslintrc from 3.2.0 to 3.3.1 (#6149)
- deps-dev: bump @types/gtag.js from 0.0.12 to 0.0.20 (#6158)
- deps-dev: bump sass from 1.77.6 to 1.91.0 (#6168)
- deps-dev: bump terser-webpack-plugin from 5.3.10 to 5.3.14 (#6169)
- deps-dev: bump @swc/jest from 0.2.36 to 0.2.39 (#6171)
- deps-dev: bump webpack from 5.97.1 to 5.101.3 (#6172)
- deps-dev: bump msw from 2.10.4 to 2.10.5 (#6173)
- deps-dev: bump eslint-plugin-react-hooks from 5.1.0 to 5.2.0 (#6175)
- deps-dev: bump react-refresh from 0.14.2 to 0.17.0 (#6179)
- deps-dev: bump @testing-library/jest-dom from 6.6.4 to 6.8.0 (#6180)
Refactor (3)
Chores (5)
-
assetVersions: remove reversion usages (#6200)
Removing usages of the django-reversion extension.
-
docs: remove
@action
leftover JSONserializer (#6153)Cleaned up unused code by removing unnecessary
JSONSerializers
from
action decorators. -
openAPI: improve API documentation structure and descriptions (#6313)
Restructure API documentation with clearer grouping of endpoints and
more detailed descriptions. -
openAPI: update HTML template title and text body (#6331)
Replace default DRF title and update the top level text
-
remove unused import (#6276)
Remove an unused import after merging #6274 in release branch.
Revert (1)
Other (1)
- [NA] Setting correct version on main deploys (#6194)
Full Changelog: https://github.com/kobotoolbox/kpi/compare/2.025.34f..2.025.37