Skip to content

Commit

Permalink
doc updates
Browse files Browse the repository at this point in the history
  • Loading branch information
martinemde committed Aug 10, 2024
1 parent 513ca08 commit 8525cc3
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 141 deletions.
47 changes: 32 additions & 15 deletions actionpack/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,56 @@
* Introduce `params.expect` as the recommended way to filter params.
`params.expect` combines the usage of `params.permit` and `params.require`
to ensure url params are filtered with consideration for the expected
types of values, improving handling of manipulated params.
* Introduce safer and more explicit params handling methods.
- `params.expect` replaces `params.require(:table).permit(:attr)`
- `params.allow` is like `expect` but for optional params.

In the following example, each version returns the same result with
unaltered params, but the first example will raise generic NoMethodError,
causing the server to return 500 and potentially sending exception notices.
Each new method ensures params are filtered with consideration for
the expected types of values, improving handling of params and avoids
errors caused by params tampering.

```ruby
# If the url is altered to ?person=hacked
# Before
params.require(:person).permit(:name, :age, pie: [:flavor])
params.require(:person).permit(:name, :age, pets: [[:name]])
# raises NoMethodError, causing a 500 and potential error reporting
params.permit(person: [:name, :age, { pie: [:flavor] }]).require(:person)
# raises ActionController::ParameterMissing, correctly returning a 400 error

# After
params.expect(person: [:name, :age, { address: [:city, :state] }])
params.expect(person: [:name, :age, pet: [[:name]])
# raises ActionController::ParameterMissing, correctly returning a 400 error
```

You may also notice the new double array `[[:name]]`. In order to
declare when a param is expected to be an array of params hashes,
this new double array syntax is used. All new methods expect arrays
to be declared this way.

In order to preserve compatibility, `permit` does not adopt the new
double array syntax and is therefore more permissive about wrong
types. Using `expect` or `allow` everywhere is recommended.

We suggest replacing `params.require(:person).permit(:name, :age)`
with the direct replacement `params.expect(person: [:name, :age])`
to prevent external users from manipulating params to trigger 500 errors.
to prevent external users from manipulating params to trigger 500
errors when the correct response is a 400 error.

Usage of `params.require` should likewise be replaced with `params.expect`.
Usage of `params.require(:id)` should likewise be replaced with `params.expect(:id)` which is designed to ensure that `params[:id]`
is a scalar and not an array or hash.

```ruby
# Before
User.find(params.require(:id)) # will allow an array, altering behavior
User.find(params.require(:id)) # allows an array, altering behavior
# After
User.find(params.expect(:id)) # only returns non-blank permitted scalars (excludes Hash, Array, nil, "", etc)
User.find(params.expect(:id)) # expect only returns non-blank permitted scalars (excludes Hash, Array, nil, "", etc)
```

`allow` behaves similar to `expect`, returning nil, array, or hash
when a param is not of the correct type or is blank or missing.
`allow` is useful when a param is optional, but needs to be permitted
if it is present.

Also adds `expect_only`, `allow_only`, and `permit_only` which raise
on the presence of unpermitted params, overriding default behavior.
Each optionally accepts a block that will yield the unpermitted keys.

*Martin Emde*

* Speed up `ActionDispatch::Routing::Mapper::Scope#[]` by merging frame hashes.
Expand Down
Loading

0 comments on commit 8525cc3

Please sign in to comment.