What's changed
Features (45)
-
AudioCell: add view details and open action buttons for audio cells (#7490)
Audio responses in the submissions table now have two separate action
buttons — "View details" and "Open" — and the inline audio player's
timer now shows hours for all recordings.The single "Open" button on audio response cells has been split into two
icon buttons: a new "View details" icon (placeholder for now) and an
"Open" icon that keeps launching the transcript/translation editor as
before. The inline mini audio player's time display is now always
visible — showing00:00:00while the duration isn't known yet, and
--:--:--if playback fails — and switches to anHH:MM:SSformat for
consistency with the newest designs. -
AudioCell: add details dialog for audio responses (#7492)
Clicking "View details" on an audio response now opens a dialog with an
audio player and a "Translate & analyze" action, instead of doing
nothing.Adds a reusable
ProcessingPromptModaldialog and wires it up to the
"View details" button on the audio submission data cell. The dialog
shows the question label, an inline audio player for the response, and a
"Translate & analyze" button that takes the user into the existing
Processing view for that submission/question. -
SSO: hide password/SSO disable for managed SSO users (#7489)
Hide password update and disable SSO UI for users with a managed SSO
social account. -
SSO: confirm modal for managed SSO signup (#7498)
Adds a confirmation modal for connecting to a managed SSO provider.
-
TextCell: add NLP action buttons for text questions (#7494)
Text question answers in the submissions table now get the same "View
details" preview and NLP actions that audio responses already have. -
accounts: require re-authentication before email change (#7525)
Changing the account email now requires the user to have authenticated
recently with their password, and also with 2FA when it is enabled.POST
/me/emails/already bundled the whole change into one call: add
the new address, promote it on confirmation, drop the old one, and send
a confirmation link to the new address.This PR adds the missing piece from the Authentication Redesign spec:
re-authentication before a sensitive account change.Browser sessions:
Browser sessions re-authenticate through allauth, which records each
step in the session. allauth's owndid_recently_authenticate()was not
sufficient because it inspects only the timestamp of the most recent
authentication record, whichever method produced it. As a result, a
password-only step would satisfy the check even for an account with 2FA
enabled.kobo/apps/accounts/reauthentication.pytherefore requires every
authentication method available to the account to be fresh within
ACCOUNT_REAUTHENTICATION_TIMEOUT(5 minutes,
environment-configurable).MFA is resolved through KPI's own
MfaAdapter, so theMFA_ENABLED
constance flag and activeMfaMethodsWrapperrows are honoured.Stateless credentials:
Stateless credentials such as token, Basic, and OAuth2 authentication
have no session for allauth to record a re-authentication in, so there
is nothing they can do to satisfy the session check.Instead, they prove their identity through the request body:
{ "email": "new@example.com", "current_password": "…", "mfa_code": "123456" }current_passwordis required whenever the account has a usable
password.mfa_codeis additionally required when MFA is enabled and
accepts either a TOTP code or a recovery code. -
accounts: add endpoint for requesting another confirmation email (#7532)
Adds POST
/api/v2/email-confirmations/, an unauthenticated endpoint
that resends a confirmation link to a registered, unverified email
address without revealing whether the address is registered.Confirmation links expire after a day. Currently, a replacement is sent
as a side effect of an unverified user trying to log in; that will be
removed, so users need an explicit way to request a new one. The caller
has just followed a dead link and has no session, so the endpoint is
anonymous.allauthhas no equivalent: its resend endpoints require
either authentication or verification-by-code, which we don't use.-
Enumeration: The same 200 and body are returned whether the address is
unverified, already verified, or unknown. Mail is sent only in the first
case. Delivery failures are logged rather than raised, since a 5xx would
itself confirm
that the address is registered. -
Which email: An account with nothing verified yet is being activated
and gets the activation email; one that already has a verified address
is mid-email-change and gets the address verification email. -
Throttling: ACCOUNT_RATE_LIMITS = False disables allauth's own
cooldown, so without a limit this is an open mail relay. Throttling is
per requested address, not per caller, so rotating source addresses
can't flood one inbox. The limit is the
EMAIL_CONFIRMATION_REQUESTS_PER_HOURConstance option (default 5; 0
disables).
-
-
auth: add auth redesign feature flag (#7446)
-
auth: add server configuration props to
/environment(#7472)The settings that control how the sign-in and account creation pages
look are now published through the/environmentAPI, ahead of those
pages being rebuilt in the main application interface. Nothing changes
for users yet.The sign-in and account creation pages are being rebuilt as part of the
main application interface rather than as separate server-rendered
pages. Those pages currently read their appearance settings, the logo,
the background image, the text shown beside the account creation form,
directly from the server while the page is being assembled. The rebuilt
pages are assembled in the browser instead, so that route is no longer
available to them.
This publishes the same values through the/environmentAPI, which the
application already reads when it starts, so the new pages can pick them
up. The existing pages are untouched and keep working exactly as they do
today.
Two values are added that the new designs call for and the server did
not previously hold: an image displayed beside the account creation
form, and a setting controlling whether the KoboToolbox logo appears. -
auth: main skeleton (#7501)
Groundwork for the redesigned sign-in and account creation screens.
Hidden behind a feature flag. -
auth: intermediate confirmation screen for managed SSO domains modifications (#7522)
This PR introduces an intermediate confirmation page in
SocialAppCustomDataAdminwhen toggling managed SSO or modifying
domains.This includes the following changes:
- Admin confirmation flow (
kobo/apps/accounts/admin.py):
SocialAppCustomDataAdmin.changeform_viewintercepts saves when managed
is toggled or domains are modified under a managed app. The confirmation
screen displays status changes (Enabling/Disabling Managed SSO),
added/removed domain lists, and plain account counts. - Reusable Queryset Logic (
kobo/apps/accounts/utils.py):
get_managed_sso_track_1_querysetreturns linked accounts, skipping
sso_exempt=Trueand anonymous users.
get_managed_sso_track_2_querysetreturns unlinked accounts with
matching email domains. These exclude users with existing InAppMessage
records matchingmessage_type=MessageType.MANAGED_SSO_REMINDERfor
idempotence.
- Admin confirmation flow (
-
auth: read-only REGISTRATION_SSO_ALLOWED_EMAIL_DOMAINS aggregate in Constance (#7470)
Added a display-only constance setting
REGISTRATION_SSO_MANAGED_EMAIL_DOMAINSthat displays a list of all
email domains configured across managed SocialApps. It is located under
General Options next to the otherREGISTRATION_*settings in the
Constance Config screenRegistered
REGISTRATION_SSO_MANAGED_EMAIL_DOMAINSsetting in
CONSTANCE_CONFIGwith field typedisabled_textareaand a note
explaining per-app management in Admin > SocialApp. The
disabled_textareafield type was added to
CONSTANCE_ADDITIONAL_FIELDS. The signalupdate_managed_sso_email_domains()helper function aggregates email
domains from managed SocialApp objects (social_app__managed=True) when
they are modified and stores them in the new read only setting in
constance.
I've also created a data migration to initialize
REGISTRATION_SSO_MANAGED_EMAIL_DOMAINSfor existing database
deployments.👀 Preview Steps
- ℹ️ Log in with a superuser / admin account.
- Navigate to Django Admin > Constance > Config
- 🟢 Confirm
REGISTRATION_SSO_MANAGED_EMAIL_DOMAINSis placed directly
afterREGISTRATION_BLACKLIST_ERROR_MESSAGE - Navigate to Account Extras > Social app custom datas
- Toggle
Managedfor a SocialApp and add an email domain - Return to Django Admin > Constance > Config
- 🟢 Confirm
REGISTRATION_SSO_MANAGED_EMAIL_DOMAINSlists the new
domain in read-only format
-
auth: custom mutator for allauth endpoints (#7549)
Adds a custom mutator for allauth endpoints to handle expected,
non-server-error 4xx responses. -
bulkProcessing: improve language blocking (#7412)
Fixed bulk translation blocking languages it shouldn't: when a project
has transcripts in more than one language for the same question, all of
those languages became unavailable as translation targets.If some submissions were transcribed in English and others in Spanish
for the same question, both English and Spanish disappeared from the
language list when starting a bulk translation, leaving no way to
translate one into the other. Now only the transcript you're actually
translating from counts. -
designSystem: move dynamic data attachments modal to mantine (#7410)
Part of ongoing design system changes to move old components to new
themed components. The dynamic data attachment modal has been updated to
use mantine -
designSystem: update bulk edit submissions form modal to mantine (#7455)
Update the bulk edit submissions form modal to mantine
-
frontend: override Switch styles for Formbuilder (#7426)
-
frontend: standalone error pages app (#7438)
New upcoming 404 and 500 error pages. Not visible to users until
switches the error handlers over. -
frontend: standalone UI language selector (#7449)
A new component for selectin interface language.
-
frontend: style textarea to match other inputs (#7285)
Kobo text inputs now look and behave consistently across
TextInput,
Textarea,NumberInput, andPasswordInput. -
map: display points across antimeridian (#7475)
Project → Data → Map now keep submissions collected on both sides of the
180th meridian together, and keep showing them while you pan around the
world.A project with points on both sides of the 180th meridian used to open
zoomed out to the whole world, with the data split between the far left
and far right edges of the map. The map now reads those coordinates the
short way round and opens on the area the data actually covers.Panning sideways no longer leaves the data behind either: markers,
clusters and heat map are drawn in every copy of the world on screen.
Auto-fitting also leaves a small margin now, so points on the outer edge
of a project's area aren't cut in half by the edge of the map. -
organizations: enable sorting for organizations members API (#7329)
Adds an ordering parameter to the organization members API
The combined list of members and invitees is sorted in
OrganizationMemberViewSet.get_queryset. The new parameter is also
documented and the schema docs were updated. Since the get_queryset
method converts the data to lists, the sorting is not done with the ORM
but with a call to the sorted funcion. -
organizations: add sorting to Members Table (#7424)
The Members table columns can now be sorted by name, status, date added,
and role. -
organizations: display SSO column in Members Table (#7411)
The Members table now has an SSO column showing which members sign in
through single sign-on. -
organizations: add search parameter to org members API (#7404)
Adding the q parameter query parsing solution to the organizations
members API so that frontend can have search filters for the members.Inside OrganizationMemberViewSet.get_queryset(), when the q parameter is
present, we now run parse() twice:- For existing members: Parsed q against
OrganizationUser fields (user__username__icontains, user__email__icontains, user__first_name__icontains, user__last_name__icontains) - For pending invites: Parsed q against
OrganizationInvitation fields (invitee__username__icontains, invitee__email__icontains, invitee__first_name__icontains, invitee__last_name__icontains, invitee_identifier__icontains)
We explicitly bypassed the global field denylist for this view by
specifying custom allowed_lookup_fields (allowing kobo_auth.user fields
like first_name and last_name and others mentioned in the ticket). I
also include the parameter definition @extend_schema_view to get the
correct documentation for the endpoint auto generated.
Since the members API uses two different models (
userfor active
members andinviteefor pending invites), the lookups work like so:- To search ONLY active members: ?q=user__email:luis@example.com
- To search ONLY pending invites: ?q=invitee__email:luis@example.com
- To search across both groups simultaneously use the generic query
(e.g.,q=luis@example.comwhich will match any of the allowed fields
usingicontains) without specifying prefixes.
- For existing members: Parsed q against
-
organizations: support q search on organization asset usage (#7515)
📣 Summary
Projects in the organization usage table can now be searched by name.
📖 Description
The usage page lists every project in the organization. This adds name
search to the data behind that table, so the search box coming in
can narrow the list instead of always showing everything.💭 Notes
- Reuses the existing
SearchFilter, chained before
AssetOrganizationUsageFilterinOrganizationViewSet.asset_usage.
Bareqterms searchname__icontains. - Fielded queries still go through the query parser's allowlist, and the
queryset was already scoped to the org owner, so nothing new is exposed. - Schema and orval client regenerated.
👀 Preview steps
- Log in as an owner or admin of an org with a few projects.
- Open
/api/v2/organizations/<org_id>/asset_usage/?q=<part of a project name>.
🔴 On main:
qis ignored and every project comes back.
🟢 On this PR: only projects whose name contains the term (case
insensitive). Aqunder 3 characters returns a 400. - Reuses the existing
-
organizations: members table search (#7523)
The members list of a team or organization can now be searched.
A search field sits next to the "Members" title. Typing at least three
characters filters the list; the search covers name, username and email.
When nothing matches, the table says so instead of showing an empty
header. -
queryParser: filter assets by multiple tags (#7388)
Filtering projects by several tags now returns only the projects that
have all of them.Combining tags in a search (e.g. "foo" and "bar") used to return
nothing. It now returns the projects tagged with every tag asked for.
Single-tag and "any of these tags" searches are unchanged. -
sidebar: add text submission component and update display settings for question types (ac8dfa7)
-
sso: add managed sso properties (#7434)
Add necessary fields for managed SSO work to Django admin.
Allows admins to toggle the
managedproperty of Social App Custom Data
and add/remove associated email domains, as well as mark users asSSO exempt. These properties are not currently functional but are added
here for ease of development. -
sso: do not allow blocked domains in managed sso (#7444)
Do not allow users to create managed SSO domains using domains that are
on the blocklist or, if one is present, not in the allowlist. -
sso: restrict how users with managed sso domains can register (#7447)
Ensure users with an SSO-managed email cannot register using a username
and password but can still register with SSO even if registration is
otherwise closed. -
sso: expose managed sso fields in /environment endpoint (#7463)
Include information about managed SSO domains in the
/environment
endpoint. -
sso: restrict account management of sso-managed accounts (#7483)
Restrict account management for users with SSO-managed accounts.
Users with SSO-managed accounts are forbidden from setting or changing a
password or unlinking their account. An admin cannot add another social
account or set a password either, but they may unlink. -
sso: add functional index for email domains (#7508)
Adds a new index to lookup email domains used by the enforce task and
the registration checksWhen searching for users with specific domains, this index built using
the expressionsplit_part(lower(email), '@', 2)will help reduce the
query execution time by around 21x compared to a sequential scan. This
is important for registration checks and also for a enforce background
task that will be triggered when an organization adds a managed domain.
This task will query auth_user to find all existing user accounts with
that domain and enforce SSO restriction rules on them.👷 Description for instance maintainers
Note that the index creation is going to block writes to the auth_user
table, so you will have to disable heavy migrations manually if this is
a concern for your instance.IMPORTANT NOTE: This index won't be supported by SQLite, only by
Postgres. -
sso: update InAppMessage for managed sso (#7516)
-
sso: actions on adding managed domain (#7517)
Update users who have managed SSO accounts to limit their login
capabilities to that SSO, and notify users with the corresponding domain
who do not yet have SSO set up that they need to do so. -
sso: optional and customizable in-app message on confirmation page (#7531)
When enabling managed SSO, admins can now choose whether to send the
in-app "connect your SSO account" message, and edit its text before
confirming.When a superuser enables managed SSO or adds a managed domain, the
confirmation screen now has a "Send in-app message" checkbox and an
editable message prefilled with the default text. Unchecking the box
skips the message. When it is checked, the message cannot be empty. -
sso: run update task on save managed SSO custom data (#7528)
Update/notify affected users when SSOs are set to be managed or new
domains are added. -
sso: enforce SSO restrictions on connecting a managed account (#7542)
🗒️ Checklist
- run linter locally
- update developer docs (API, README, inline, etc.), if any
- for user-facing doc changes create a Zulip thread at
#Support Docs Updates, if any - draft PR with a title
<type>(<scope>)<!>: <title> - assign yourself, tag PR: at least
Front endand/orBack end
orworkflow - fill in the template below and delete template comments
- review thyself: read the diff and repro the preview as written
- open PR & confirm that CI passes & request reviewers, if needed
- act on any greptile review below a 5/5 score or leave comment
explaining why you won't - delete this checklist section from the final squash commit
before merging
When a user of a managed domain connects their SSO account, disable
other login methods and remove any in-app notifications. -
sso: add provider detail endpoint (#7496)
This PR adds a public API endpoint that resolves an SSO provider's URL
identifier into its display name, so the upcoming React login screens
can render the "Log in with …" page that Django templates render today.This PR adds GET
/api/v2/social-apps/<provider_id>/, which returns the
provider_idandnamefor a configured Social Application.Some organizations sign in through an SSO provider that is deliberately
not shown on the public login page. Its Social Application has
is_publicunchecked, and they distribute a direct link to their own
staff, for example:https://<kobo-server>/accounts/oidc/nca/login/.
Only thencapart varies. Today, that URL renders a shared Django
template titled "Log in with {{ SocialApp.name }}". The same template is
used for every provider on every server.The Authentication Redesign deletes that template and rebuilds the
screen in the SPA. To render it at a route like
#/login/oidc/<provider_id>, the frontend needs to turnprovider_id
into a display name and distinguish a real provider from a typo so it
can show the appropriate 404. The frontend cannot read the database
directly, so it needs this endpoint.Nothing changes for users yet. The existing login pages are untouched.
-
sso: withdraw reminders when managed SSO is turned off (#7545)
Turning managed SSO off, removing a managed email domain, or deleting
the SSO provider now withdraws the in-app reminders it sent.When an organization's SSO provider stops being managed, or one of its
email domains is removed, users on those domains no longer see the
"Update your account" reminder asking them to link their SSO account.
They can set a password and link other social accounts again. Deleting
the provider itself has the same effect. Reminders left behind by
earlier changes are cleared by the nightly job. -
sso: make the signup-closed message configurable (#7544)
Admins can now customize the message shown on the sign-up page when
registration is closed.When account registration is turned off, anyone opening the sign-up page
sees a fixed "Sign Up Closed" notice. Admins can now replace that text
with their own, for example to point people to their organization's SSO
login. If nothing is configured, the default notice stays as it was. -
subsequences: run automatic qualitative analysis on text questions (#7458)
Automatic qualitative analysis and translation now run on text
questions, without needing a transcript first.Both features used to read their input from a transcript, so they only
worked on audio and video questions. A text question has nothing to
transcribe, so they were unavailable there.They now read the answer straight from the submission when the question
is a text question. Audio and video keep working as before, through the
transcript. Enabling an action on a question type that doesn't support
it, like transcription on a text question, is now refused up front
instead of failing later.Nobody declares what language a typed answer is in, so translation uses
the form's own language when it knows it, and otherwise lets the
translation service detect it. Very long answers are the exception: they
go through a batch API that cannot detect a language, so those ask for
the form language to be set. -
usage: add support link (#7459)
Adds a link to support.
Bug Fixes (23)
-
account: after updating password leave form (#7478)
After successfully updating account password, we now redirect back to
Security route. -
accounts: restrict users to one linked SSO account (#7224)
You can now only connect one single-sign-on (SSO) provider to your
account at a time; attempting to link a second while one is already
connected is blocked with a clear error.Previously the "connect SSO" action was only hidden in the UI once an
account was linked, but the underlying link was still reachable, so a
user could connect a second SSO provider by navigating to it directly.
This change enforces the one-SSO-per-account rule on the server, so the
restriction holds regardless of how the request is made.👷 Description for instance maintainers
Adds a
SocialAccountAdapter(kobo.apps.accounts.adapter) overriding
pre_social_login, registered via the newSOCIALACCOUNT_ADAPTER
setting. On aconnectflow, if the authenticated user already has a
SocialAccountfor a different provider/uid, the link is rejected and
a dedicated error page is rendered via allauth's own
render_authentication_error()helper (the same helper allauth uses for
its other SSO errors) explaining that only one SSO account can be linked
at a time. Reconnecting the same account, normal SSO login, and signup
are unaffected. The guard sits in allauth'scomplete_loginbefore the
account is created, so it covers both the classic redirect flow and the
headless API (/api/v2/allauth/…). -
api: fix schema for Imports Create to support XLS/base64 library upload payload (#7150)
Fixed the ImportCreateRequestSerializer schema definition to include the
missing fieldsbase64Encoded,library,desired_type,totalFiles.
The OpenAPI and Orval output files were updated to reflect this change. -
attachments: match media filenames across unicode normalization forms (#7467)
Media files with accented characters in their name now upload and play
back instead of vanishing from the data table.A recording called something like
Guérisseur.oggwould upload without
any error, then land in the data table as plain text with no way to play
or download it. Same thing on edits, and re-uploading never helped.
Those files stay attached to their question now. -
attachments: resolve question xpath on the name the client sent (#7609)
Two files attached to the same submission are no longer mixed up when
their names differ only by a character the storage layer rewrites.A submission answering two media questions could show one of its files
under the wrong question, if the two file names differed only by a
character the server rewrites when storing them, a space against an
underscore for instance. Both names ended up recorded the same way, so
only one of the two questions could be told apart, and the other file
followed it. The file the client sent is now matched on the name they
sent it under, so each one goes back to its own question. -
auth: remove unnecessary managed sso domains sync in migration (#7591)
Remove the call to
sync_managed_sso_email_domainswithing the
migration0010_socialappcustomdata_managed_socialappmanageddomain.py
because it's unnecessary. It runs as a signal when social app custom
data changes. -
bulkProcessing: use rootUuid in bulk processing code (#7420)
Fixes bulk transcription, translation and approval failing with an
"Unknown submission UUIDs" error when the selection included submissions
that had been edited. -
bulkProcessing: review button showing up wrongly (#7425)
The "Review" button for an automatic transcription now appears only in
the column of the language it was transcribed into, instead of in every
transcript column of that row. -
celery: schedule trash bin and project ownership dispatchers on
kpi_queue(#7513)Moves four scheduled orchestration tasks from
kpi_low_priority_queue
tokpi_queue:- trash_bin.task_restarter
- trash_bin.garbage_collector
- project_ownership.task_restarter
- project_ownership.garbage_collector
These tasks only enqueue work and finish in milliseconds, but they were
scheduled onto the same queue as the long-running deletions and
transfers they dispatch. When that queue backs up, the recovery path is
stuck behind the backlog it exists to clear.The deletion and transfer tasks themselves are unchanged and stay on
kpi_low_priority_queue. -
designSystem: change project top tabs to old component (#7416)
Brings back the old project top tabs compoenent
-
exports: include submissions in XLS (legacy) exports of transferred projects (#7623)
XLS (legacy) exports are no longer empty for projects that were
transferred to another owner.Once a project had been transferred to another account, its XLS (legacy)
export came out with the column headers and no submissions. The table
view and the CSV (legacy) export still showed everything. Projects that
moved to an organization when their owner joined it were affected too,
since that is also a transfer. The export now contains the submissions
again. -
formbuilder: duplicate imported question name (#7428)
Fixed a bug where adding the same question or block from the Library
multiple times gave every copy the same data column name in Formbuilder. -
massemails: fix edge cases for one-off mass email campaigns (#7555)
Fixes edge cases where one-off mass email campaigns (
frequency = -1)
could be accidentally resent if remaining enqueued records transitioned
to STALE or if the Celery worker process terminated before the campaign
was finalizedget_users_for_config()now excludes users who already have a
terminal status (SENT, FAILED, STALE) under that one-off config- Any one-off campaign that has already run and has 0 enqueued records
is disabled immediately, even if all remaining records went STALE.
send_emails()now filters onjobs__isnull=Falseinstead of
pk__in=sender.config_ids. - If an unclosed one-off config has records and no eligible recipients
remaining,generate_mass_email_user_lists()markslive = False
directly without creating an emptyMassEmailJobre-enqueueing records - Included new unit tests to validate that the edge cases are handled
correctly
-
organizations: sort role by level of privilege instead of alphabetically (#7430)
Organizations members are now sorted by level of privilege in the
members API when usingordering=role(previously they were sorted
alphabetically) -
qrcode: drop qrcode.react in favour of react-qr-code (#7499)
Internal frontend updates
-
sso: allow users to unlink unamanged accounts (#7539)
Fixes a bug that was preventing users from unlinking unmanaged SSO
accounts -
sso: fix label in constance (#7558)
Corrects a label in Constance, pointing users to the correct place to
edit managed domains. -
storybook: broken test (#7469)
-
tos: hide fields for MMO users (#7491)
Members of a multi-member organization can now accept the Terms of
Service — the form no longer asks them for organization details they
aren't allowed to change. -
trashBin: give each trash type its own restart budget (#7514)
Splits
MAX_RESTARTED_TASKSinto three per-type settings for trash bin
deletions, and stopstask_restarterfrom swallowing its own soft time
limit.Implements the findings from #7422 and supersedes it.
The investigation showed that limiting how many deletions
task_restarterenqueues does not limit DB pressure: concurrency is set
by the size of the worker pool, not by how many messages are published.
Two things from #7422 are worth keeping on their own merits, and this PR
is just those two.- Per-type restart budgets. _restart_stuck_tasks() sliced all three
trash types with settings.MAX_RESTARTED_TASKS, which
project_ownership/tasks.py also uses with a different "batch per run"
meaning - one shared name, two unrelated behaviours. Each trash type now
has its own setting:
- MAX_RESTARTED_ACCOUNT_DELETIONS
- MAX_RESTARTED_PROJECT_DELETIONS
- MAX_RESTARTED_ATTACHMENT_DELETIONS
All default to 100, so behaviour is unchanged. They are separate because
the three deletions do not cost the same.- Do not swallow
SoftTimeLimitExceeded. In the enqueue block it was
caught by the generic except Exception and logged as Could not restart
#, which is wrong on both counts: nothing is wrong with the
object, and the restarter had already claimed it, so it sat untouched
until the next stuck threshold ~76 minutes later. It now restores
date_modifiedand re-raises.
- Per-type restart budgets. _restart_stuck_tasks() sliced all three
-
trashBin: suspend owner submissions during project deletion (#7553)
Permanently deleting a project or an account no longer fails when that
account keeps receiving submissions while the deletion runs.While a project is being permanently deleted, incoming submissions for
all projects of that project's owner are paused. Data collection apps
get the usual "temporarily unavailable" answer and retry on their own,
so no data is lost. The pause is lifted as soon as the deletion ends,
whether it succeeded or not. Until now a submission arriving in the
middle of a deletion could make the deletion fail and get rescheduled. -
xlsImport: match project languages to XLSForm languages (#7417)
Re-uploading an XLSForm now sets the project languages to exactly the
languages of the uploaded file, instead of keeping languages that were
removed from it.Uploading a form with three languages and re-uploading it with two used
to leave the third language defined with empty strings, and removing all
languages created an unnamed language. Project languages now always
match the file: a language stays only if at least onesurveyor
choicescolumn still uses it, and a file with plainlabelcolumns
brings the project back to "no languages defined". -
xlsImport: block translated XLSForm missing language-specific columns (#7473)
Uploading an XLSForm that has translations but leaves some columns
untranslated (like a plainhintnext tolabel::English (en)) is now
blocked with a clear error instead of creating a broken project.Until now, importing such a form quietly added an "Unnamed language" to
the project, which could break the form builder, or silently dropped the
missing translations. The import now fails right away with a message
naming the column, e.g. "Thehintcolumn is not translated". Forms
with no translations at all import as before.
Continous Integration (1)
- du: remove du as a pipeline trigger INFRA-598 (#7484)
Build & Dependencies (5)
-
deps: bump the actions-deps group across 1 directory with 3 updates (#7471)
-
deps: bump the actions-deps group across 1 directory with 2 updates (#7547)
-
deps-dev: bump fast-uri from 3.1.5 to 3.1.7 (#7530)
-
frontend: bump insecure js-yaml versions (#7427)
Updated the
js-yamldependency to patch a set of denial-of-service
advisories. -
frontend: bump mobx-react (#7480)
Testing (2)
Refactor (9)
-
assets: drop deprecated calls to ReactDOM.findDOMnode (#7495)
Internal improvements for frontend
-
auth: move sessionStore logout handling to RQ (#7550)
Removes logout handling from sessionStore and moves it to react query
hooks called by components. -
frontend: SSOT for columns order (#7389)
Columns are now listed in the same order in every place that shows them:
Data Table, "hide fields" menu, Single Submission modal, and the field
picker in Downloads. -
frontend: replace KoboSelect with Mantine Select (#7408)
Migrated multiple different selects from deprecated
KoboSelectto
Mantine'sSelect. -
frontend: replace react-select with Mantine Select (#7462)
A few dropdowns are now unified to look like all the other dropdowns.
-
frontend: remove TextBox use Mantine (#7487)
Text fields across the app now share one consistent look and size, and
password fields — including your API key — are revealed with a toggle
inside the field itself. -
library: typescriptize and de-mixin LibraryNewItemForm (#7497)
Update icons in Library "NEW" modal.
-
library: move template and collection creation modals to mantine (#7506)
Part of ongoing process to modernize old frontend components. Updates
the modals for library creation of collections and templates. -
project: typescriptize formSummary (#7507)
Chores (6)
-
CODEOWNERS: add James K to replace Kalvis, remove Jackie, reduce John (#7505)
-
bulkProcessing: remove feature flag (#7439)
-
constants: refactor loose interval constants into one place (#7465)
Internal refactor
-
frontend: drop use-immer (#7479)
-
frontend: drop unused dependencies (#7482)
-
mfa: remove the django-trench backend dependency (#7396)
Internal cleanup — removed an old, unused authentication library. No
change to how two-step verification (MFA) works.Two-step verification already runs on our current authentication stack;
an older library it used to depend on was left behind with no live data
still using it. This removes that old library and its leftover database
tables. Nothing changes for you — enabling, using, and disabling
two-step verification all behave exactly as before.
Revert (3)
Full Changelog: https://github.com/kobotoolbox/kpi/compare/2.026.33b..2.026.37