Release 26.11.11
Upgrade notes
Please read these before upgrading: this release closes several authentication flaws and removes the tinyMCE widget.
Security fixes in login, RPC dispatch and the page store: upgrading is strongly recommended (see Security below). Changes that can affect downstream code:
RPCs of a login-protected page require a session. Before login, only the calls the login page itself declares (its
LoginComponentrpcs, therootenvFormfields, the buttons of extension packages) are served; a method can also declare itself with@public_method(sessionless=True)(#1828).A page method called over the websocket must be decorated with
public_methodorwebsocket_method: undecorated methods are refused.A client changes the rootenv only on a
serverpaththe page declared, and never writes server-only page-store paths; a refused change is logged as a warning (#1830, #1851).At login, rootenv keys sent by the client that no
onUserSelectedhook set and no login form field edits are dropped, and their names are logged (#1828, #1851).
tinyMCE widget removed (#1793):
tinyMCEandExtendedTinyMCEare gone together with the vendored TinyMCE bundle;joditEditoris the only HTML editor (#1728) and thetheme.tinymce_betasys preference is removed. Stored widget tags that still nametinyMCE(e.g. survey questions) must be migrated tojoditEditorbefore upgrading.New default palette: with no color variant selected, mimi and joanna use a Carbon Cool Gray palette with a blue accent; it can also be chosen explicitly as color variant
gray. Existing color variants and custom variant files are unchanged.tbl.sql()/pkg.sql()model scripts are namedsqlCode(); they run on PostgreSQL only, and a model declaring them stops the migration on other adapters.Dependencies:
weasyprintcapped below 66, whose versions up to 69 can paginate forever when Arial Narrow falls back to a wide font (#1825); thesyspackage requireswatchdogbelow 7 (#1844).
New features
Database and audit
External audit (new package
gnrcore:audit):audit='external'on a table installs PostgreSQL triggers that version records and queue every change;gnr @<instance> audit batchturns the queue into audit events, Bag columns diffed path by path. Field rules via columnaudit=True/Falseand tableaudit_whitelist/audit_blacklist. Record History and Table History palettes on the TH form and list.SQL scripts in the model:
tbl.sqlCode()andpkg.sqlCode()declare inline or file-based PostgreSQL scripts, with{name}placeholders for model properties; the migrator applies them in a final phase when their md5 changes, one per tenant schema on multi-tenant tables.Multidb: hosting preferences on the storetable record override the workspace preferences key by key, shown read-only in the workspace preference page; PostgreSQL dbstore provisioning is resumable across workers.
Inline documentation (experimental)
Enabled with <experimental><gui inlinedoc="true"/></experimental>.
Docs as MyST Markdown files in the private
inlinedocstorage (a folder of the instance when not configured), addressed by convention (field:,grouplet:,page:,table:,package:) and edited in place by users with the documenter tags.The "?" of pages, views, forms, fields, cards and blocks opens the doc in a popup or the matching section of the published Sphinx manual in a resizable help panel; "Open in the manual" opens a window of its own. The pages of a session share the doc icon states.
Grids and table handlers
External queries: a page can open a table page with conditions loaded in its query editor (topic
th_external_query), with order, limit, caption, search mode, a grid view or a grouped view, and optionally the save query dialog open.Customizable query menu:
th_handlePyQueries,th_handleCustomQueryActionsand thequeryMenuItemhook.A package can scope its
_packagestable handler overrides to its own context withth_override_scope='context', in itsconfig_attributesor on its tag ininstanceconfig.xml(#1299).Column value filter: values in descending order, a period selector on date columns (#1725); works on aggregated columns.
Row dragging in the grouped view grid.
A literal
rowTemplatekeeps its handlers (#1456).
Grouplets
groupletCard: a grouplet with a chrome band (chevron, title, doc icon, kebab, checkbox), standalone or inside agroupletGrid; collapsible, tinted when a field inside is in error.groupletGrid: copy and paste of rows (tab-separated, with header), file-list-like selection on rows and cards across grids, drag with a drop slot, Export Excel and Print presets for the selected rows,defaultRowvalues from a datapath or==expressions,additem_focus,fillRowand wide cards in a responsive grid, tab label template and ordering, Italian catalogue.groupletWizardForm:keepToolbarkeeps the th top bar.
Forms and widgets
joditEditorbrought to parity with tinyMce (#1721).dbSelect
auxColumnsmenu switches to a multiline layout when too wide (auxColumns_multiline) (#1767).genro.dlg.promptand dynamic forms can use a formlet layout (formlet=True, default from<gui use_formlets="true"/>) (#1700, #1701).multiUploaderDialogopens on a large drop area and lists files like a file browser, with progress bars.dynamicFieldsPane:fld_*kwargs become defaults of every dynamic field; placeholder when empty.Validation error tooltip appears after 1.5s on hover.
Frameindex: New Window button next to the menu search box.
Site, services and printing
A package providing
not_logged_redirectcan redirect a page without a logged user instead of showing the login dialog.kajennprinthtmltopdf implementation rendering on a kajenn print server, selected byKAJENN_PRINT_URL(#1707).The weasyprint service logs once when "Arial Narrow" falls back to a font that is not metric-compatible, with the fix (
fonts-liberation-sans-narrow, as in the Docker image) (#1825).Optional genro-storage backend for local, raw and aws_s3 mounts, behind
<experimental><storage use_genro_storage="true"/>and thegenro_storageextra (#1238).
Security
Login: the user status (banned, new, waiting, invited) and 2FA are enforced server side;
login_confirmUseracts only on the user verified bylogin_checkAvatar;login_createNewUserhonors thenew_userpreference and accepts only the form fields; password recovery mail goes to the stored address.Login form calls (#1828, #1845): before
doLoginonly the calls the login page declares are served; dbSelect fields run with the recorded table, columns and condition, and condition parameters that read the rootenv take their value from the server; rootenv values derived by the form are read on the server.2FA (#1769): the "remember this device" cookie is signed and expires after the configured days, re-enrolling or disabling 2FA revokes it;
confirmOTPwrites only the logged user's record.RPCs of a login-protected page require a session; without a session only already used components, of the same package, can be mixed in.
Websocket calls follow the same auth rule and reach only public methods.
Page store (#1830, #1837): client changes never reach server-only paths (2FA state, the user to confirm, the mixin set, user local tags); the rootenv changes only on declared serverpaths, so a client can no longer pick a partition or identity key outside what the server allowed;
rpc_setInServerapplies the same guard; store changes and pings reach only pages of the caller's connection.Window messages that load data, queries or grid structures are accepted only from the page's own origin (#1847).
api_keys.privatekept server side inrpc_main(#1534).prosemirror-view bumped to 1.42.9 (paste XSS, GHSA-c8x8-7fp4-3x9w).
inlinedoc: documenter tags resolved server side, private storage, validated uploads.
Bugfixes
SQL and database
Migration creates indexes declared with
tbl.index()(#1806).Db-events are recorded again for every table, so
autoCommitbatches commit their writes (e.g.email.message.newMessage) (#1821).Store-local table caches keyed on the current dbstore (#1794); storetable query skipped when no store database exists (#1775); store discovery ignores the user's partition (#1816); workspace discovery locks released before migration; deleted workspace register stopped only after commit; a multidomain store without its
_mainpref_row reads as empty preferences, sognr db migrate '<instance>.*' -uno longer fails on it (#1838).Multidb sync handles tables with deferred foreign keys.
adm.userobjectreads on sqlite (#1373); an empty Bag column is copied in the old record so in-place changes reachfieldsChanged;sysRecordcreates on the current connection inside a transaction (#1625); attachment tables work ingnr app cleanup(#1792).
Forms, grids and widgets
Widgets bound to
path?attrwrite only that attribute (#1827).Widgets: a filteringSelect re-resolves its value when its values change (#1812); a typed datetime keeps its value on blur (#1785); a comboMenu does not open on a readOnly or disabled field (#1786).
Formlet: an unlabeled checkbox gets a placeholder label only beside a labeled field, keeps its colspan and shows its own doc button (#1850).
Grid: column filter on values columns, empty values and Select all; the filter icon opens on every click and is never a resize or drag area (#1722, #1742); a removed row no longer moves the selection; treeGrid scroller off the last row (#1774); grouped view export from its frozen selection (#1773).
Forms: a removed node takes its invalid fields with it; dynamic required fields no longer block groupletGrid entry rows; a hidden calculated field keeps its formula value (#1719); wizard steps follow
avoidPendingChangesDialog; the linkerBox template wraps again (#1404).Stores: a selection store queues one reload while its query runs (#1740); a node bound to a container recomputes on row insert or delete (#1712).
A prompt opened while another closes keeps its data; prompt buttons translated; searchbox filters on any text change; tooltipPane follows its opener while scrolling (#1737); Dates from another window stay Dates; dialog
autoSizepadding (#1704); labledbox no longer double-wrapped; jodit loads values overmaxLength(#1727); many theme and border fixes.
Site, web and services
Remote content (lazy forms, dialogs) subscribes the serverpaths it declares (#1851).
A failed upload is reported instead of treated as success (#1814); uploaded files kept out of page registration (#1710); multipart files closed with the response (#1684).
getRelatedSelectionpasses its columns to the query (#1374);page.exceptionknows the sql exceptions (#1747); GnrException messages localized with the given localizer (#1744) and their warnings stay until closed;statusTextcorrect over HTTP/2 (#1741); polling left to the root page (#1597).Storage path segments with several
:answer 404 (#1699); a storage record changed by another process is reloaded (#1682); relative storages rebuilt when the parent service changes.Task scheduler starts when
gnrcore:sysis reached only through the package closure (#1612);gnrtaskworker --codehonored again (#1718); the development server reloads again with watchdog 7 (#1844).Email: proxy record forgotten before retry (#1804), missing attachment files fail fast (#1800),
proxy_syncidle when mailproxy is disabled (#1790), missing default account reported (#1751).Login: new window skips an empty dialog (#1743);
loginExtrahooks run only on an actual login (#1732); the "Expired session" dialog shows on the login page too (#1828).Undeclared packages report and boot warnings clarified.
Other
Infrastructure
Docker images: release images are built only from
release-*tags (version andlatest), thedevelopimage nightly at 04:00 UTC or on demand; both are built only when the Python and JavaScript test suites pass, and a release reaches PyPI only after its image is built.PostgreSQL test database names are unique per run (#1366); pytest pinned in CI; async fixture wrapper forwards
delattr.wkhtmltopdf install and test removed.