Commit Graph

1279 Commits

Author SHA1 Message Date
Mike Dalessio 6b8a571fd3 Merge pull request #2383 from basecamp/flavorjones/3722-self-assign
Fix "M" hotkey to not use stale user ID from the fragment cache
2026-01-16 13:47:18 -05:00
Mike Dalessio 2527f07365 Fix "M" hotkey using stale user from fragment cache
Add a SelfAssignmentsController to resolve the current user at request
time, avoiding the use of an incorrect user id baked into a cached URL.

ref: #2211 originally added the "M" hotkey
ref: https://app.fizzy.do/5986089/cards/3722
2026-01-16 13:41:33 -05:00
Jorge Manrubia 99a8d12c9d Merge pull request #2382 from basecamp/attachment-take-2
Solve problem when Action Text raises on missing attachables
2026-01-16 17:36:10 +01:00
Jorge Manrubia 4ab1e3ff7d Solve problem when Action Text raises on missing attachables
Reverts the previous patch. The problem was that I hadn't update
 Lexxy in the saas version https://github.com/basecamp/lexxy/pull/596
2026-01-16 17:32:41 +01:00
Mike Dalessio 9c76002bc1 Completing a step removes stalled status from UI
Add `updatedAt` to stalled bubble options so JS can check if the card
was recently updated, matching the `Card::Stallable#stalled?`
logic. Refresh the bubble via Turbo Stream when a step is updated.

This should have been part of #1625

Fixes https://app.fizzy.do/5986089/cards/3668
2026-01-16 09:58:21 -05:00
Rosa Gutierrez ee636f1994 Delete orphaned watches and pins when a card is moved to a private board
For watchers and users with pins that don't have access to the private
board where the card was moved to.
2026-01-14 19:38:15 +01:00
Rosa Gutierrez 5e099c4c06 Delete pins belonging to cards in a board with revoked access
As part of cleaning up inaccessible data in the board after revoking
access.
2026-01-13 16:25:59 +01:00
Andy Smith 64fdbf6b8f Clean up blank slates 2026-01-12 15:37:06 -06:00
Jeremy Daer 006e61ea58 Allow ActionText embed reuse and safe purge (#2346) 2026-01-12 10:30:18 -08:00
Stanko Krtalić eceb6c9b43 Add self-service account deletion (#2246)
* Add self-service account deletion

* Disable access to cancelled accounts & implement Stripe interactions

* Add tests

* Fix failing tests

* Remove cancelled accounts from lists

* Fix incorrect redirect

* Use _path instead of _url for consistency

* Don't track how far the inicieration job got

We still want the step tracking so that the job can be interrupted. But, since the scope is idempotent, we don't need to track how far it got.

* Specify the exact time when the data will be deleted

* Fix crash due to unadvancable cursor

* Rename up_for_incineration to due_for_incineration

* Regenrate the schema

* Fix incorrect path check

* Migrate the SQLite schema

* Only show the cancel button on cancellable accounts

* Check that a subscirption method exists before calling it

* Ignore job failures due to missing records when an account gets deleted

* Skip sending notifications on cancelled accounts

* Use collbacks to integrate

* Add a blank line between queue_as and discard_on

* Break checks into methods

* Inline methods

* Rename Account::IncinerateJob

* Run migrations

* Migrate SQLite
2026-01-12 14:21:05 +01:00
Jorge Manrubia 3457c871e1 Revert "Add CJK (Chinese, Japanese, Korean) search support" 2026-01-08 21:07:14 +01:00
Jorge Manrubia ca68264c65 Merge pull request #2306 from basecamp/draft-new
Use a dedicated resource for showing cards in draft mode
2026-01-08 17:30:19 +01:00
Jorge Manrubia db804b8450 Merge pull request #2299 from Maklu/fix-cjk-search
Add CJK (Chinese, Japanese, Korean) search support
2026-01-08 12:00:46 +01:00
Jorge Manrubia f58a1aeb31 Use a dedicated resource for showing cards in draft mode
Mobile team needs this. Also, this lets us get rid from some conditionals for handling
both modes with a single template.

https://3.basecamp.com/2914079/buckets/44843469/messages/9437287330
2026-01-08 10:40:21 +01:00
Jorge Manrubia 6d05ab428e Remove engagements
We are not using this anymore!
2026-01-07 16:43:33 +01:00
Jorge Manrubia e34716a537 Merge pull request #2221 from pinzonjulian/patch-1
Fix test state pollution caused by filter/search_test
2026-01-07 16:40:18 +01:00
Jorge Manrubia fb6bcaa18e Merge pull request #2227 from scart88/main
Redirect back to account settings page when the user role is changed …
2026-01-07 16:27:05 +01:00
Jorge Manrubia 8efb778f53 Merge pull request #2237 from dilberryhoundog/fix-closed-cards-from-not_now
Fix: destroy "not now" state when closing cards, enables "indexed_by=closed" expected behaviour
2026-01-07 16:15:14 +01:00
Jorge Manrubia 6e765a114c Merge pull request #2294 from basecamp/refresh-drafts
Make sure new card drafts are refreshed when reused
2026-01-07 15:49:46 +01:00
LU 366588e263 Add SQLite FTS5 support for CJK search
- Split each CJK character into individual tokens for FTS5 indexing
- Add stem_content callback to SQLite adapter to pre-process content
- Stem search queries before matching against FTS5 index
- Update stemmer tests to reflect character-splitting behavior

This enables CJK search on SQLite installations where the FTS5
tokenizer cannot natively segment CJK text.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 17:51:20 +09:00
LU 2a4fbecbda Add CJK (Chinese, Japanese, Korean) search support
The search functionality was silently dropping CJK characters because:

1. Query sanitization used `\w` which only matches ASCII word characters
2. Stemmer split by whitespace, which doesn't work for CJK languages
3. Highlighter used `\b` word boundaries that don't apply to CJK

This commit fixes all three issues:

- Query: Use `\p{L}\p{N}` (Unicode letters/numbers) instead of `\w`
- Stemmer: Preserve CJK characters as-is without stemming, since CJK
  languages don't have stemming rules like English
- Highlighter: Skip word boundary matching for CJK terms

Also extracts `CJK_PATTERN` to `Search` module to avoid duplication.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-06 17:22:42 +09:00
Rosa Gutierrez 5f390f72df Support local installations where the app is loaded over HTTP
In this case requests won't be performed from a secure context [1] and
the browser won't send the Sec-Fetch-Site header. This means non-GET
requests will be rejected because CSRF protection will fail.

With this change, we allow these requests with missing Sec-Fetch-Site
headers if:
- They happen over HTTP
- The app is not configured to force SSL

The Origin check happens in any case.

[1] https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Secure_Contexts#potentially_trustworthy_origins
2026-01-05 18:50:14 +01:00
Jorge Manrubia 85bfa7aa48 Rename method 2026-01-05 16:01:25 +01:00
Jorge Manrubia 5f38e8957e Reapply "Make sure new card drafts are refreshed when reused"
This reverts commit 045ddf78f3.
2026-01-05 15:58:29 +01:00
Jorge Manrubia 045ddf78f3 Revert "Make sure new card drafts are refreshed when reused"
This reverts commit 3008011175.
2026-01-05 15:58:16 +01:00
Jorge Manrubia 3008011175 Make sure new card drafts are refreshed when reused
To deal with old timestamps messing with card ordering and so.

https://app.fizzy.do/5986089/cards/3495
2026-01-05 15:57:48 +01:00
Jeremy Daer 0eefd67b68 Block IPv4-compatible IPv6 addresses in SSRF protection (#2273)
The SSRF filter checked ipv4_mapped? but not ipv4_compat?, allowing
addresses like ::169.254.169.254 to bypass the link-local check and
reach cloud metadata endpoints.

Changes:
- Add ipv4_compat? check to block deprecated IPv4-compatible format
- Rename private_address? to blocked_address? (more accurate - method
  blocks more than just RFC 1918 private ranges)
- Add IPv6 test coverage for both mapped and compat formats

Both ipv4_mapped and ipv4_compat formats are blocked entirely as
defense-in-depth: DNS never returns these formats, so they only
appear in attack scenarios.

HackerOne: #3481701
2025-12-29 21:45:06 -08:00
Mike Dalessio f952b953e6 Add test coverage for autolinking multiple URLs 2025-12-29 12:21:02 -05:00
Mike Dalessio 97d8d6a395 Add "noopener" to autolinks' rel attribute 2025-12-29 12:21:02 -05:00
Mike Dalessio 4579f7cd61 Avoid string manipulation when autolinking.
Instead, let's use a Loofah scrubber which will create DOM nodes
directly. This should be faster and is a tiny bit simpler, as well as
removing a potential HTML injection vector.

Also, add "noreferrer" to all `mailto:` links (already present on URLs).
2025-12-29 12:21:00 -05:00
Rosa Gutierrez f66a2dc1ba Consider user avatars always public
Avatars are purposely accessible without authentication
(5e3b5b6d7c) because they can be in public
collections. Trying to restrict this by checking whether they're in fact
present in some public collection is rather expensive, so let's keep
them public.
2025-12-26 19:33:26 +01:00
Rosa Gutierrez 196d685f8d Implement authorization for Active Storage endpoints
Consider blobs attached to any public records accessible to anyone with
the URL.
2025-12-25 21:22:36 +01:00
Stanko Krtalić 24c20ad55f Merge pull request #2244 from basecamp/expose-card-ids-on-comments
Expose the card ID and URL on comments
2025-12-24 08:50:47 +01:00
Stanko K.R. 822c3bb2ad Expose the card ID and URL on comments 2025-12-24 08:45:31 +01:00
Rosa Gutierrez 3fcf5a9d08 Require authorization for direct uploads
Respond with 403 to JSON requests that are unauthorized, instead of
redirecting.
2025-12-23 11:08:51 +01:00
Dylan a005391724 Fix: allow destroying "not now" state when closing cards
- Update `Card::Closeable` to destroy associated "not now" state during close.
- Add new tests to verify closure behavior for different column types, including "not now".
2025-12-23 13:43:03 +08:00
Jason Zimdars 563c530e3e Merge pull request #2213 from basecamp/welcome-letter
Stub welcome letter for newly created accounts
2025-12-22 10:17:41 -06:00
Stanko K.R. 0df667f4fb Fix HTML injection in webhooks through card titles 2025-12-22 12:20:32 +01:00
scart88 ba887225a5 Redirect back to account settings page when the user role is changed or when the user is removed from an account. 2025-12-22 10:47:23 +02:00
Jason Zimdars bc4745c6ce Add a test 2025-12-20 18:12:42 -06:00
Julián Pinzón Eslava 12928f530b Refactor search test to use instance variables
The included SearchTestHelper disables transactional tests and has a specific setup that does not use fixtures.

This test however, ignores the setup and uses fixtures directly by creating comments and publishing cards making test state unpredictable. 

By using the records set by the helper instead of fixtures, the state of the system is not polluted.
2025-12-21 00:23:21 +11:00
Jeremy Daer bd6c1cf34f Storage: harden reconcile for concurrent writes and fix board transfer (#2096)
* Storage: harden reconcile for concurrent writes and fix board transfer

Reconcile now uses two-cursor approach: captures cursor before and after
the storage scan, aborting if they differ (entries added during scan).
Job retries 3x with 1-minute waits and limits concurrency to 1 per owner.

Board transfer now correctly moves storage for card description embeds
and comment embeds, not just direct attachments. Uses batched queries
to handle cards with thousands of comments efficiently.

Also fixes N+1 queries in attachment grouping via lookup maps.

* Storage: fix per-attachment reconcile and enforce no blob reuse

The storage ledger tracks per-attachment (not per-blob) as a business
abstraction for quotas. This fixes reconcile to match that model and
adds enforcement to prevent blob reuse in tracked contexts.

* Reconcile now uses joins(:blob).sum() for per-attachment counting
* New validation prevents reusing blobs across tracked attachments
* Race-safe storage_total creation with create_or_find_by
* Job efficiency: skip find_by when object already available
* Backfill script checks per-attachment, not just per-blob
2025-12-19 13:07:32 -08:00
Stanko K.R. e0270c6c49 Clean up interfaces
I talked to the mobile team, and to keep things simple we agreed to send
the token via a cookie.
2025-12-19 19:21:57 +01:00
Stanko K.R. 23fc7b594f Split tests by controller or responsibility 2025-12-19 19:21:57 +01:00
Stanko K.R. 1a1f4a077b Simplify auth logic 2025-12-19 19:21:57 +01:00
Fernando Olivares cddddcf83a Fix due to unit test when creating with invalid emails 2025-12-19 19:21:57 +01:00
Fernando Olivares fb487f598c Restore sessions_controller test on creating invalid email address 2025-12-19 19:21:57 +01:00
Fernando Olivares be447f90ba Move magic link api tests to their own files 2025-12-19 19:21:57 +01:00
Fernando Olivares 6be20e215b Rename test to clarify what they're about 2025-12-19 19:21:57 +01:00
Fernando Olivares 6e8d6a3df0 Update to always return a pending auth token for JSON responses. 2025-12-19 19:21:57 +01:00