Skip to content

v3.5.0

Choose a tag to compare

@lehni lehni released this 11 Oct 16:31
· 534 commits to main since this release

Behaviour changes

These changes close security holes or fix data loss, but existing apps may notice them:

  • server (security): Relation requests are authorized for their parent member: accessing a relation requires the parent's member get authorization, changing it also its member patch authorization unless the relation's action has an authorize setting of its own, also when allow doesn't route these actions, with '$owner' and '$self' referring to the parent (#207). The parent is resolved through its member.get and scope, with one extra lookup per relation request, so relations of hidden parents answer 404; before, relation actions without their own authorize setting were accessible without any authorization.
  • server (security): dito's graph methods, upsertAndFetch(), the arrays of patchAndFetch() / updateAndFetch() and insert() with arrays reject objection's graph control properties '#dbRef', '#unrelate' and '#delete' with a GraphError (400), as they let clients relate rows of other parents and override noUnrelate / noDelete. This reverts the keeping of '#unrelate' / '#delete' in related references of 3.3.1 and 3.4.0; code that needs them can use objection's own insertGraph() / upsertGraph(). '#id' and '#ref' are still accepted.
  • server (security): Unsigned asset files from allowed import sources (allowedImports) are only accepted with keys in the format of generated keys, and disk storages keep their file paths inside their folder. Before, the keys of such files weren't checked and could address files outside the storage folder.
  • server: Array patchAndFetch() / updateAndFetch() / upsertAndFetch() and collection PATCH / PUT requests only save the models themselves, like patch() / update() of single models: their related models are left alone instead of being updated or inserted. Use the *DitoGraph() methods to save relations (#206, closes #191).
  • server: Requests with transactions fail when committing fails, e.g. on deferred constraints, instead of answering with success while knex silently loses the data (knex#6141).
  • admin: emit() calls its callbacks like EventTarget dispatches events: the callbacks registered when the emit starts, skipping the ones removed in the meantime, e.g. by off() or by once() in a concurrent emit. Callbacks added during an emit are called from the next emit on, unlike 3.2, and callbacks removing themselves or others, including once() callbacks, no longer make the emit skip the callbacks after them (#210).

Fixes

  • admin: Clicking Create while an item is still loading no longer shows that item in the create form.
  • admin: Leaving an unsaved create form for an existing item loads that item instead of keeping the empty one.
  • admin: Forms nested in views without resources provide the view's data as rootItem and parentItem.
  • admin: Components placed directly in views without resources provide the view's data as rootItem, also to the validation rules and exclude / process callbacks of nested schemas (#193).
  • admin: The children of tree objects can be edited: their edit links lead to their forms (#189).
  • admin: Closed children of a tree list's root reopen when a form below them is opened, like deeper levels (#197).
  • admin: After logging out and in again, nested forms get their routes again (#187).
  • admin: Forms with tabs keep their selected tab while the forms of their list or tree items are open, and when returning from them (#192).
  • admin: Only the form of the last route follows the tab in the route's hash, which fixes an endless loop with tabbed forms of tree items in tabbed forms (#211).
  • admin: Reloading the page on the form of a list or tree item in a tab no longer shows a blank parent form.
  • admin: Applying the form of a tree item keeps the item's children instead of deleting them.
  • admin: Tree lists that are the only component of a view get edit links that match their routes.
  • admin: Tree lists render without a route component, e.g. in dialogs.
  • admin: Tree items show the keyboard focus ring, also when selected.
  • server: 'commit' listeners of request transactions run after the commit: errors in them still fail the request, after the data is committed, but no longer trigger the 'rollback' events. Transactions that handlers roll back themselves without an error emit 'rollback' instead of 'commit', so that e.g. imported asset files are cleaned up (#209).
  • server: member.get overrides receive the same this for from: 'member' parameters and $owner checks as for routed requests.
  • server: One-to-one relation controllers without member.get overrides support $owner checks and pass the related model to from: 'member' parameters. On empty relations, the actions that resolve the member ($owner checks, from: 'member' parameters) answer 404, like their member routes (#194).

Restored behaviour of 3.2.7

3.3 and 3.4 changed some behaviour that apps may rely on. 3.5.0 restores it; changes are planned for 4.0:

  • server: The color type accepts any string again. 3.3 only accepted hex colors and color keywords.
  • server: Collection PATCH / PUT requests and array patchAndFetch() / updateAndFetch() insert root models without ids again. 3.3.1 skipped them. Note that this doesn't check post permissions. Related models are no longer inserted, see above (#206).
  • admin: Separate emits of the same event don't wait for each other again. 3.4.0 queued them, which made a handler that awaits an emit of its own event hang. See above for the callbacks called by each emit (#210).

Behaviour changes of 3.3 and 3.4 that stay

  • admin: Errors in load handlers are shown as notifications instead of only being logged.
  • admin: Relative download URLs like files/1 resolve against the API, with its authentication.
  • admin: The upload property of files in upload values is { id, success } instead of the upload object.
  • server: from: 'member' parameters and $owner checks use member.get overrides. Overrides should pass modify on to super.get(), otherwise locks and scopes are lost. See the new section in docs/controllers.md (#188).

API and docs

  • server: New overridable controller methods: handleRequestAuthorization() authorizes requests beyond their own authorize setting, authorizeMember() authorizes a member like its get or patch action, and getActionAuthorize() returns an action's authorize setting. The id of fetchMember() is optional: one-to-one relation controllers then fetch their related model.
  • ui: A focus-ring SASS mixin for keyboard focus, with a color option.
  • docs: docs/controllers.md describes the authorization of relation requests, member.get overrides including their this in one-to-one relations, and the members of one-to-one relations and their 404s.

Internal

  • The coverage thresholds are enforced in CI.
  • Development uses objection 3.5.0; the peer dependency stays ^3.3.0.
  • Tests cover known bugs of nested forms, routing and options.