Commit Graph

35 Commits

Author SHA1 Message Date
Jeremy Daer a52b6f1c87 Add explicit wrap_parameters to all controllers (#2680)
* Add explicit wrap_parameters to controllers for flat JSON API support

Virtual attributes (has_rich_text, has_one_attached, delegated setters,
ActiveModel attrs) are not in Model.attribute_names, so wrap_parameters
auto-detection silently drops them from flat JSON requests. Add explicit
include: lists matching each controller's permitted params.

* Convert short-form wrap_parameters to explicit include: lists

Defense-in-depth: these controllers only have real-column params today,
so auto-detection works, but explicit lists prevent future regressions
if virtual attributes are added.

* Add flat JSON param tests for all wrap_parameters controllers

17 new tests covering every controller with wrap_parameters, verifying
that flat (unwrapped) JSON payloads are correctly wrapped and processed.
Focuses on virtual attributes that would be silently dropped without
explicit include: lists.
2026-03-09 21:47:05 -07:00
Jeremy Daer 723c8180b4 Add JSON response format for full SDK/CLI coverage (#2675)
* Add JSON response format to void-response controller actions

Add respond_to blocks with JSON format to 14 controllers that
previously only rendered HTML or Turbo Stream responses. JSON
callers get head :no_content (or :created/:ok for push
subscriptions, distinguishing new vs existing).

Covers: board involvements, board/account entropies, column
reordering, card readings, card publishing, user roles, user
avatars, account settings, notification settings, join codes
(with 422 error branch), and push subscriptions.

* Add steps index endpoint with JSON view

Add index action to Cards::StepsController so SDK/CLI callers
can list all steps for a card. Reuses the existing _step.json
partial.

* Add JSON views for paginated card list endpoints

Add show.json.jbuilder for stream, not-now, and closed column
endpoints. No controller changes needed — set_page_and_extract_
portion_from and fresh_when already work format-agnostically.

* Add JSON search endpoint with distinct-card pagination

JSON search paginates distinct Card records (via the existing
Card.mentioning scope with .distinct) rather than Search::Record
objects. This ensures page boundaries, Link headers, and counts
reflect unique cards — no short pages from post-pagination dedup.

ID-match searches return a uniform single-element Card[] array
through the same pagination path.

* Add JSON views for settings and configuration endpoints

Add show.json.jbuilder for account settings (name), join codes
(code, usage_count, usage_limit, url, active), and notification
settings (bundle_email_frequency). Tests for show and update
were added in the void-response commit.

* Add JSON response format to data exports

Create returns 201 with export id, status, and created_at so
callers can poll. Show returns any-status exports for JSON (not
just completed) with a download_url when ready, or 404 for
missing/other-user exports.

* Extend access token JSON API

Add index.json and _access_token.json partial for listing tokens.
Add JSON format to destroy. Include id and created_at in the
create response alongside the existing token/description/permission
fields.

* Fix ambiguous precedence warning in export JSON view

* Assert X-Total-Count pagination header in streams JSON test

* Address review feedback

- Guard steps index against HTML requests (redirect to card)
- Normalize created_at to UTC in access token and export JSON
- Add deterministic ordering (.latest) to search JSON pagination

* Return 406 for HTML requests to steps index instead of redirect

* Add wrap_parameters for flat SDK JSON payload compatibility

Five controllers infer the wrong wrapper key from their class
name, so flat JSON bodies like {"role":"admin"} fail with 400.
Add explicit wrap_parameters declarations:

- Users::RolesController → :user
- Notifications::SettingsController → :user_settings
- Account::JoinCodesController → :account_join_code
- Account::SettingsController → :account
- Boards::EntropiesController → :board

Add integration tests that send flat (unwrapped) JSON payloads
for all seven param-bearing endpoints to prove SDK compatibility.

* Address PR review feedback

- Use 201 Created (not 204) for all create actions: publishes, readings,
  left/right positions, push subscriptions
- Simplify push subscription to always return :created (no 200/201 variance)
- Remove superfluous respond_to block from steps#index
- Merge exports#show into single respond_to block
- Move export download_url conditional out of inline args
- Ensure join code active is explicitly boolean
- Remove extra parens from search controller assignment
- Add blank lines between format blocks for readability

* Return JSON bodies on create actions

Create actions for boards, cards, columns, comments, and steps now
render the resource as JSON (via their show views) instead of returning
empty 201 responses with only a Location header. SDKs expect a JSON
body they can deserialize into the created resource.

* Return JSON bodies on reaction create actions

Card and comment reaction creates now render the reaction as JSON
instead of returning empty 201 responses, consistent with the other
resource-creating endpoints.

* Allow access tokens API without account scope

Access tokens are identity-level (not account-scoped), so the
controller needs to work with bearer token auth and no account slug
in the URL. Skip require_account so the bearer token auth path
can proceed.

Also fix involvement test to send params in JSON body (not query
string) to match real SDK usage.
2026-03-09 11:39:49 -07:00
Alp Keser a6eb331710 Fix query parameter name 2026-02-12 14:55:34 +03:00
Alp Keser b8793bfec3 Add include_unread param to tray API and vary cache 2026-02-12 14:55:34 +03:00
Alp Keser 80546a6b47 Include read notifications in the tray API response 2026-02-12 14:55:34 +03:00
Stanko K.R. 36ee253a1a Stack notifications everywhere
We had client-side notification stacking in the tray since launch, but now we want to stack notifications in the notifications page, in API responses and in email bundles.
2026-02-12 10:29:50 +01:00
secretpray 6895135977 Fix deprecation warnings for skip_before_action :verify_authenticity_token
Replace deprecated `skip_before_action :verify_authenticity_token` with
`skip_forgery_protection` to resolve Rails deprecation warnings.

Changes:
- app/controllers/notifications/unsubscribes_controller.rb
- saas/app/controllers/stripe/webhooks_controller.rb
2026-01-12 18:44:35 +02:00
Stanko K.R. bf51950007 Add API for reading notifications 2025-12-10 09:23:52 +01:00
Mike Dalessio 79c9ea2ce1 Remove a bunch of N+1s
related to notification and comment rendering
2025-11-27 11:08:45 -05:00
Jorge Manrubia 03a345609e Baseline replacing collection with board across code 2025-11-05 13:31:54 +01:00
Stanko K.R. 87d9c3cd01 Make unauthenticated access permit unauthorized access 2025-11-04 09:02:36 +01:00
Jorge Manrubia 8aead31200 Fix: mark all as read wasn't refreshing in the notifications screen 2025-11-04 06:12:30 +01:00
Stanko Krtalić 98755844a1 Remove the internal API
* Bind sessions to identities
* Remove references to the identity token
* Move email changes to identity
* Move account menu into a turbo-frame
* Create tenants from a tenanted route
2025-10-31 16:26:08 +01:00
Jorge Manrubia 958deab2c7 Fix: problem with notifications not dismissing due to HTTP caching
The problem was related to tying the invalidation to the association of unread notifications. Its
cache key can remain constant as you read old notifications.

https://app.box-car.com/5986089/cards/2620/edit
2025-10-31 11:34:42 +01:00
Jorge Manrubia 4527dcbeda Remove unnecessary filtering code
After removing collections from the filtering menu, there was quite a good cleanup here pending
2025-10-03 10:56:34 +02:00
Jorge Manrubia d533f05c7b Use vanilla resources for handling notifications 2025-09-10 09:17:57 +02:00
Jorge Manrubia 4f1c5ee113 Add http caching to notifications 2025-09-09 12:39:28 +02:00
Jorge Manrubia 6f2670d6dd Merge main into bundle-emails branch and resolve conflicts 2025-09-01 11:49:20 +02:00
Andy Smith 2036071ddd Remove collection filtering where it's not needed 2025-08-28 12:22:48 -05:00
Jorge Manrubia e4ab1366be Add unsubscribe links and headers for emails
https://3.basecamp.com/2914079/buckets/37331921/todos/9002504172
2025-08-28 16:59:24 +02:00
Jorge Manrubia 53144a379c Add option to change the bundled email notification frequency 2025-08-28 11:56:40 +02:00
Andy Smith 27ac5b1fc1 Menu on notification settings page 2025-08-27 13:55:54 -05:00
Jason Zimdars 4276aad5a7 Mark notifications as unread from the index 2025-07-23 17:01:59 -05:00
Mike Dalessio 53ebb509d8 Broadcast when all notifications are cleared
Then make the turbo response to clearing all notifications a no-op.

This has the bonus side effect of properly clearing the notifications
try on all open pages.

ref: https://fizzy.37signals.com/5986089/collections/2/cards/796
2025-07-03 12:05:41 -04:00
David Heinemeier Hansson 9cea403acd Make sure that any card getting read does not empty out the notifications tray
Since we wont rehydrate it
2025-04-18 16:32:27 +02:00
David Heinemeier Hansson 4bb9085737 Hide implementation detail of reading 2025-04-16 16:41:22 +02:00
David Heinemeier Hansson 5932bf9316 This is rare enough that a redirect is fine 2025-04-16 16:21:16 +02:00
David Heinemeier Hansson 73f272f132 Use one controller for all notification readings 2025-04-15 19:14:50 +02:00
David Heinemeier Hansson 2ea898324f We can just set the namespace directly in the class name 2025-04-15 16:36:40 +02:00
Jorge Manrubia 723e6d94f5 Rename bubbles => cards 2025-04-09 14:50:58 +02:00
Kevin McConnell 942dd27e5c Sort buckets on notification settings 2025-02-27 12:17:32 +00:00
Jason Zimdars 530b6e4a90 Stub notifications settings screen 2025-02-21 17:25:44 -06:00
Jason Zimdars 190e046479 Mark all notifications as read from the index 2025-02-21 12:12:00 -06:00
Kevin McConnell 5d5dc8fb73 Wire up notifications "Mark all as read" button 2025-01-21 14:37:41 +00:00
Kevin McConnell c4f50fa634 Move notifications to tray controller 2025-01-16 17:48:38 +00:00