Commit Graph

4730 Commits (5ebc1af91e96ca065ea55f20e94de5d874a442c8)

Author SHA1 Message Date
Your Name 30440c5e00 Add isMysql/isMariadb split helpers for MySQL-vs-MariaDB divergence
For the rare cases where SQL must differ between MySQL and MariaDB,
add DatabaseDriver::isMysql()/isMariadb() and db_is_mysql()/db_is_mariadb()
alongside the existing grouped isMysqlMaria()/db_is_mysql_maria().
2 weeks ago
Your Name e3b6cebf27 Fix MariaDB driver detection and reblog caption null inserts
Laravel 11 exposes MariaDB as a dedicated 'mariadb' driver, so
config('database.default') === 'mysql' checks silently misclassified
MariaDB as the non-mysql (postgres) branch.

- Add App\Util\Database\DatabaseDriver with isMysqlLike()/isPgsql()
  plus db_is_mysql_like()/db_is_pgsql() global helpers.
- Route all database.default driver checks through the helpers so
  MySQL and MariaDB are treated as one group.
- Use '' (not null) for share/compose caption+rendered, valid whether
  the column is nullable or NOT NULL (it is NOT NULL on MySQL/MariaDB).
- Guard pgsql strtolower() in registration against missing fields.
- Scope CustomEmoji::duplicateShortcodes to the grouped column for
  Postgres GROUP BY validity.
- Remove stale Postgres guard in status:dedup; use havingRaw for
  cross-driver HAVING.
2 weeks ago
Your Name 729396302a fix(federation): swallow ConnectionException on synchronous AP delivery
queueDelivery() runs synchronously from the v1 follow/unfollow endpoints
(via Helpers::sendSignedObject), which commit local state before delivery
and have no try/catch. After the Http::send() rewrite, a ConnectionException
from a momentarily-unreachable remote was rethrown out of queueDelivery(),
turning a best-effort delivery into a 500 for the user after the follow/
unfollow was already persisted. For unfollows, a retry then hit the
isFollowing==false branch and never re-sent the Undo, diverging state.

Treat transport failures (ConnectionException) as best-effort on this
single-delivery path: log, record host health, and return without
propagating. Other exception types (invalid sender/destination, signing,
serialization) still throw, matching pre-rewrite precondition behavior.

Also widen SendUpdateActor's per-user catch from HttpException to Throwable
so a single bad host no longer aborts a fleet-wide actor update (the old
HttpException catch is dead for ConnectionException/invalid-destination).
2 weeks ago
Your Name 8a4567a5c2 Isolate fanout delivery failures from StatusDelete local cleanup 2 weeks ago
Shlee a1abf10010
Merge pull request #7254 from pixelfed/fix/oidc-dangerzone-lockout
Mark OIDC login session password-confirmed to fix dangerzone lockout
2 weeks ago
Your Name fbca487bcd Mark OIDC login session password-confirmed to fix dangerzone lockout 2 weeks ago
Shlee 78447646b8
Merge pull request #7253 from pixelfed/fix/remote-update-media-validate-before-orphan
Validate remote update attachments before detaching existing media
2 weeks ago
Your Name 9b829ca56e Validate remote update attachments before detaching existing media 2 weeks ago
Shlee 1d7ee48f2e
Merge pull request #7252 from pixelfed/fix/v2-media-can-post-role
Enforce can-post role check on POST /api/v2/media
2 weeks ago
Your Name 3a23606573 Enforce can-post role check on POST /api/v2/media 2 weeks ago
Shlee a510682122
Merge pull request #7251 from pixelfed/fix/delete-account-purge-status-edits
Purge status_edits on account and status deletion
2 weeks ago
Your Name 60284a871e Purge status_edits on account and status deletion 2 weeks ago
Shlee 7a5626766e
Update PrivacySettings.php 2 weeks ago
Your Name 7b90bc8699 Fix remove-all follower purge chunkById key and gate the route behind dangerzone 2 weeks ago
Your Name cfbdabdd61 Send verification email for admin-invite users that require verification 2 weeks ago
Shlee 1fffdef464
Merge pull request #7247 from pixelfed/fix/report-object-id-integer-validation
Validate report object_id as a positive integer to fix 500
2 weeks ago
Your Name b4bd3c87a0 Validate report object_id as a positive integer to fix 500 on array input 2 weeks ago
Your Name fe382bdb86 Extend story author-key TTL instead of overwriting so it survives to the longest-lived story 2 weeks ago
Your Name 5ec239404b Import Purify facade in ApiV1Controller to fix larastan class.notFound 2 weeks ago
Daniel Supernault fbd0922fd0
Update Helpers 2 weeks ago
Daniel Supernault a27033d2fd
Update LoginController 2 weeks ago
Daniel Supernault 538a11cccd
Update LoginController 2 weeks ago
Daniel Supernault 96acfb3d91
Update InboxWorker, improve handling 2 weeks ago
Daniel Supernault 13a8a255f6
Update ActivityPub Inbox update handling 2 weeks ago
Daniel Supernault d2a45ee4d3
Update ApiV1Controller 2 weeks ago
Daniel Supernault 22108f8f11
Lint PostImportController 2 weeks ago
Daniel Supernault 914ab1196a
Update StoryComposeController 2 weeks ago
Daniel Supernault b0ca632026
Update unbookmark endpoint 2 weeks ago
Daniel Supernault 1cead5cf60
Update in-app registration 2 weeks ago
Shlee 88137649a3
Merge pull request #7242 from pixelfed/fix/home-timeline-null-account
Guard home timeline filter against null account
2 weeks ago
Your Name b13c374f21 Guard home timeline filter against null account 2 weeks ago
Your Name f1e4536d19 Invalidate notification cache when deleting a status 2 weeks ago
Daniel Supernault e0550c441c
Fix AdminApiController profiles endpoint, dont include deleted accounts 2 weeks ago
Daniel Supernault 6a2208087c
Update AdminStatsService, fix reports_monthly stat 2 weeks ago
Daniel Supernault b2deebb72b
Update AdminApiController, fix typo 2 weeks ago
Daniel Supernault 6232d35d90
Update AccountService and AdminApiController 2 weeks ago
Daniel Supernault 96229868ff
Update AdminApiController, fix missing resource 2 weeks ago
Daniel Supernault 70bab963bc
Fix NetworkTimelineService 2 weeks ago
Daniel Supernault 27bc6e792a
Update AdminApiController and PublicTimelineService 2 weeks ago
Your Name 9d839f7b5a Fix missing email verification dispatch on settings email change 2 weeks ago
Daniel Supernault fbd52dd8fc
Improve federation handling 2 weeks ago
Daniel Supernault 5fc343dd40
Update federation fanout 2 weeks ago
Daniel Supernault a3160cdd23
Update PublicApiController, fix getStatus to use database check 2 weeks ago
Daniel Supernault f371376789
Fix StatusDelete, handle StatusService deletion 2 weeks ago
Daniel Supernault ed63be4d4f
Update HttpSignature, improve signing 2 weeks ago
Daniel Supernault 868e09b64d
Update AP Delivery Service, fix signing and delivery 2 weeks ago
Daniel Supernault 6e0d8454fd
Fix StatusDelete job, add logging 2 weeks ago
Daniel Supernault 1e6ce226e0
Refactor StatusController 2 weeks ago
Daniel Supernault 7a98ebfe56
Delete NotificationEpochUpdate.php 2 weeks ago
Daniel Supernault 15b46186b4
Delete NotificationEpochUpdatePipeline.php 2 weeks ago
Daniel Supernault 9e69d449d5
Update NotificationService 2 weeks ago
Your Name 7a420112bf Normalize cropped story images to the 1080x1920 canvas (#7215)
cropPhoto() used coverDown(1080, 1920), which only downscales, so an
undersized crop was stored at its original size (e.g. 110x196). Remote
servers then dropped the image story for not matching expected story
dimensions while videos federated. Use cover() so small crops are scaled
up to fill the canvas.

Note: the complementary remote-side validator relaxation (StoryFetch
validateImageFile) is tracked separately and not included here.
2 weeks ago
Your Name c0f29d4a4b Fix web notifications not loading (#7195)
Notification status hydration compared item_type strictly against
Status::class (App\Models\Status). Rows created before the App\ ->
App\Models\ namespace migration store the legacy 'App\Status' morph-map
alias, so the comparison failed and favourite/comment/mention
notifications came back with no attached status. The web UI filters those
out client-side but keeps paginating (response never empty), leaving the
infinite-scroll loader spinning forever.

- NotificationTransformer + Mastodon NotificationTransformer: match both
  the legacy alias and the current FQCN when hydrating status.
- NotificationService::buildNotification: same alias-aware deleted-item guard.
- NotificationService::getMaxPage/getMinPage: filter out unrenderable
  notifications (status-type without a hydrated status) so the endpoint
  never returns rows the UI discards, fixing pagination termination; warn
  on unexpected notification types.
- Tests for transformer hydration (legacy + current), renderable filtering,
  the unexpected-type warning, and pagination termination.
2 weeks ago
Your Name 341351c47e Remove sha256 verification from MediaMoveStorageLocalToCloud
original_sha256 is the pre-optimization upload hash and can never match the
optimized local file, so comparing against it is not a valid integrity
check for migration. Drop the --verify-sha256 option and the checksum step
entirely; verify now relies on cloud-object existence and size parity.
2 weeks ago
Your Name 438560415a Revert debug-by-default in MediaMoveStorageLocalToCloud
The cloud migration failure (stale original_sha256 verify) is resolved, so
the temporary default-on debug is no longer needed. Restore --debug to a
bare, off-by-default flag and remove the debugEnabled() string-parsing
helper.
2 weeks ago
Your Name 441a94e731 Make original_sha256 verify opt-in in MediaMoveStorageLocalToCloud
original_sha256 is the hash of the file as originally uploaded, but the
async optimize pipeline (ImageResize/ImageUpdate) rewrites the local file
in place and never updates that column. Verifying the current local bytes
against it made every optimized image fail with sha256_mismatch, so the
migration reported moved=0 and exited 1.

Add a --verify-sha256 flag (off by default) that gates the checksum step.
By default verify relies on cloud-object existence and size parity, which
is the only signal that actually describes the uploaded copy. Add tests
covering both the default (migrates) and opt-in (fails) paths.
2 weeks ago
Your Name b2a068b934 polish 2 weeks ago
Your Name 0c68b6a680 Add failure logging to admin:MediaMoveStorageLocalToCloud and enable debug by default
The scheduled command only surfaced 'exit code 1' with no cause. Add
structured Log::error entries at every failure path (cloud disk
unresolvable/unconfigured, cloud storage disabled, invalid --before-id,
candidate fetch failure, per-media failure with full context, and a
run-level summary when failures occur).

Also make --debug default to true (now a valued option) so production
runs emit verbose routing detail while this is investigated; pass
--debug=false to silence.
2 weeks ago
Your Name 8aa3144745 Fix story video upload probe path (#7203)
apiV1Add passed an absolute path to FFMpeg::open(), which laravel-ffmpeg
resolves relative to the local disk root, producing a doubled path and an
ffprobe 'Unable to probe / No such file or directory' failure.

Open the file via the disk instead: FFMpeg::fromDisk('local')->open($path)
for local storage, and an on-demand local disk rooted at the temp dir for
cloud storage.

Adds feature tests that pin the disk-relative path resolution.
2 weeks ago
Shlee ad686571bf
Change storage size calculation from floor to ceil 2 weeks ago
Shlee caffc40a45
Fix URL construction for API timeline request 2 weeks ago
Shlee 289251985a
Merge pull request #7199 from pixelfed/fix/story-publish-validation-exception
Laravel 13 Prep: Stop swallowing overlay ValidationException into a generic 500
2 weeks ago
Your Name 62d3bc8406 Stop swallowing overlay ValidationException into a generic 500
publishNext() throws ValidationException::withMessages() for invalid
story overlays (bad text/hashtag/mention/url/type), but the enclosing
catch (\Exception $e) caught it too, since ValidationException extends
Exception. Clients got a generic 500 "Failed to create story" instead
of the intended 422 with field-level errors, and the log was flooded
with ordinary user-input validation failures logged as server errors.
Catch ValidationException separately, roll back, and rethrow it so
Laravel's exception handler renders the normal 422 response.
2 weeks ago
Your Name 8fa18ff8c6 Fix dangling DB transactions in CustomFilterController
store() and update() open a manual DB::beginTransaction() but had early
return paths (duplicate keyword, keyword not found, per-filter keyword
limit) that hit neither DB::commit() nor the catch block's rollback,
leaving the transaction open past the end of the request. Add the
missing DB::rollBack() call on each early-exit branch, matching the
manual-transaction pattern used elsewhere in the app.
2 weeks ago
Your Name bbe7cfa8e1 Split Horizon into priority-based supervisors, add balanceCooldown
and notification routing

All 15 queues previously ran through one auto-balanced supervisor.
Horizon's `balance: auto` does not honor queue array order for
priority, so despite queue names implying priority ('high' vs 'low'),
a burst on any one queue could starve any other sharing that
supervisor - e.g. a burst of mmo (image/video optimization, 23
dispatch sites, CPU/IO heavy) could delay high-queue DM/follow
delivery just as easily as it could delay low-queue background work.

Split into 4 supervisors grouped by actual job characteristics
(checked via grep across every ->onQueue() call site, not guessed):
- supervisor-priority: high, inbox, pushnotify, follow, default,
  shared - user-facing federation/DM/notification delivery.
- supervisor-fanout: feed, story, groups - bursty timeline/story
  fanout writes triggered by posts, likes, and follows.
- supervisor-media: mmo - image/video optimize/resize/thumbnail.
  Runs a fixed worker pool (balance: false) instead of auto-scaling,
  so it can't claim workers away from the other pools under load.
- supervisor-background: low, delete, adelete, move, intbg - imports,
  crawling, account deletion/migration; not time-sensitive.

Moved the shared supervisor shape into `defaults` (keyed per
supervisor name, per Horizon's own merge behavior) so `environments`
only needs to override what actually differs, instead of each
environment fully redefining supervisor-1 from scratch. Existing env
vars (HORIZON_MAX_PROCESSES, HORIZON_MIN_PROCESSES,
HORIZON_BALANCE_STRATEGY, HORIZON_SUPERVISOR_*) keep governing the
priority supervisor for continuity with existing deployments; the
three new supervisors get their own HORIZON_*_MAX_PROCESSES vars
with conservative defaults.

Also:
- Added balanceCooldown: 3 explicitly (previously relied on
  SupervisorOptions' own constructor default of the same value -
  behavior is unchanged, just no longer implicit).
- Wired LongWaitDetected notification routing
  (Horizon::routeMailNotificationsTo/routeSlackNotificationsTo) to
  new optional config('horizon.notification_routing') keys, sourced
  from env vars. Previously these were hardcoded, commented-out
  examples with nowhere to actually alert on the `waits` thresholds
  already configured below.

Verified by actually starting `php artisan horizon` and inspecting
`horizon:supervisors`: all 4 supervisors registered with exactly the
intended queues, supervisor-media correctly running fixed (non-auto)
balancing. Cross-checked every ->onQueue() call site in app/ against
the new supervisor queue lists - exact match, no queue dropped or
duplicated. Full test suite (715/715) and Larastan clean.
2 weeks ago
Shlee 140221fe90
Merge pull request #7192 from pixelfed/refactor/str-of-to-native
Laravel 13 Prep: Replace Str::of() fluent chains with static Str::/native calls
2 weeks ago
Your Name a424493420 Replace Str::of() fluent chains with static Str::/native calls
Aligns with the app's dominant convention (171 static Str:: calls vs
24 Str::of() chains). Uses Str::afterLast() for the repeated
"segment after last slash" pattern, Str::matchAll() where a
Collection return is needed, and native explode()/substr() where a
plain array/string suffices.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2 weeks ago
Your Name 277b8aa970 Use now() helper instead of Carbon::now() for current-time access
Aligns with the app's dominant convention (413 now()/today() call
sites vs 12 Carbon::now()). Carbon::parse() calls are untouched since
they parse arbitrary date strings, not current-time access.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2 weeks ago
Daniel Supernault 6ddc803ae1
Fix SoftwareUpdate notices 2 weeks ago
Daniel Supernault bbd7618c46
Update StoryService and add has_story to AccountTransformer 2 weeks ago
Daniel Supernault 7975ba9c75
Fix StoryCarousel cache invalidation 2 weeks ago
Daniel Supernault 915879ff57
Update account suggestions 2 weeks ago
Daniel Supernault 9aafa37364
Update ApiV1Controller.php 2 weeks ago
Daniel Supernault 6a33716870
Update ApiV1Controller, fix account suggestions 2 weeks ago
Your Name ce073ffc92 Merge remote-tracking branch 'origin/staging' into feature/honeypot-spam-protection
# Conflicts:
#	routes/web.php
2 weeks ago
Your Name 5a9c235922 Backfill storage_used on upgrade via queued job + data migration
Repair accounts whose storage counter drifted before the self-heal logic
existed (#7169). A data migration dispatches RecalculateAllUserStoragePipeline
to the low queue so the deploy is not blocked while every user is recomputed
from source. The job is unique and idempotent, so re-runs are harmless.

- RecalculateAllUserStoragePipeline: chunked recalc of all active users
- Migration dispatches the job (no inline heavy work during deploy)
- Test covers bulk recalculation from actual media
2 weeks ago
Your Name 61a1c30756 Self-heal stale storage_used on read to unblock stuck accounts
UserStorageService::get() now recalculates from source when the cached
counter is missing or older than STALE_AFTER_HOURS, instead of returning a
possibly-inflated cached value. This is what unblocks a user stuck at the
account size limit: the limit check on their next upload attempt reads the
freshly recalculated real usage rather than the drifted value (#7169).

The upload flow reads get() and enforces the limit BEFORE the write-path
heal runs, so a blocked user could never self-heal via upload/delete alone.
Healing on read closes that gap and makes the scheduled reconciler a
belt-and-suspenders safety net rather than a requirement.

A fresh counter is still trusted as-is (no per-read SUM). Adds tests for the
stale-get recompute and fresh-get trust paths.
2 weeks ago
Your Name 10559c23e3 Fix larastan noAuthFacadeInRequestScope in LoginController
Replace Auth::check() with $request->user() !== null in confirmEmail(),
which already has the request in scope, and drop the now-unused Auth
facade import. Resolves the 2 remaining project-wide larastan errors.
2 weeks ago
Your Name f467dc04d5 Remove unused CACHE_KEY constant from UserStorageService
The constant was never referenced; the service reads and writes the
storage_used column directly on the User model rather than via cache.
2 weeks ago
Your Name 26d3e8bb8e Self-heal stale storage_used on upload/delete hot path
Make increaseStorageUsed/decrementStorageUsed recalculate from source when
the cached counter is older than STALE_AFTER_HOURS (168h) or never
calculated, so an affected user is corrected the next time they upload or
delete without waiting for the nightly reconciler. Callers save/delete the
media row before calling these, so the from-source recalc already reflects
the change and the incremental delta is skipped on the recalc path.

- Add UserStorageService::STALE_AFTER_HOURS and isStale() helper (no extra
  query: reads the already-loaded model), with defensive Carbon parsing
- Cast users.storage_used_updated_at to datetime so freshness comparisons
  work on a Carbon instance
- Add tests for stale/fresh/never-calculated increase and decrement paths
2 weeks ago
Your Name 6496904293 Fix account storage limit not freeing on media deletion (#7169)
users.storage_used only ever grew: uploads incremented it but no deletion
path decremented it, so users hit the account size limit even when their
real media usage was well below it.

- Decrement storage_used in MediaDeletePipeline when media is removed
- Add UserStorageService::increaseStorageUsed / decrementStorageUsed as the
  fast, symmetric hot-path counter updates (floor-based, clamped at zero)
- Refactor the 6 upload call sites to use increaseStorageUsed instead of
  duplicated inline writes (also fixes ceil/floor drift vs the reconciler)
- Add (user_id, size) covering index so per-user SUM(size) is not a full
  table scan (INPLACE/LOCK=NONE, skipped on sqlite)
- Add user:storage:recalculate command to repair affected accounts, with a
  daily --stale=168 scheduled reconciler to correct any drift
- Add regression tests for the pipeline and UserStorageService
2 weeks ago
Daniel Supernault edcf978755
Update AccountTransformer.php 2 weeks ago
Daniel Supernault 194c881cb2
Update ResetPasswordController 2 weeks ago
Daniel Supernault 1d96c94054
Refactor Auth, remove expensive middleware 2 weeks ago
Daniel Supernault 57e7eef082
Fix StoryIndexService 2 weeks ago
Daniel Supernault 13aa36efb4
Update ApiV1Controller.php 2 weeks ago
Shlee 519b1b94dc
Refactor comments in DangerZone middleware
Removed redundant comments to clarify code functionality.
2 weeks ago
Shlee 5d38faa257
Merge pull request #7166 from shleeable/fix/dangerzone-logout-clear-2fa-session
Invalidate session on DangerZone forced logout to clear 2FA state
2 weeks ago
Your Name 58e8a4922d Invalidate session on DangerZone forced logout to clear 2FA state 2 weeks ago
Shlee e60082b9b9
Merge pull request #7165 from shleeable/fix/media-blocklist-indexed-lookup
Use indexed query for media blocklist lookups and allow removing inactive hashes
2 weeks ago
Your Name e8f2b06afe Use indexed query for media blocklist lookups and allow removing inactive hashes 2 weeks ago
Shlee 9cf879d375
Merge pull request #7163 from shleeable/fix/status-lexer-no-autolink-fanout
Deliver posts regardless of profile no_autolink flag
2 weeks ago
Your Name 9e14151228 Deliver posts regardless of profile no_autolink flag 2 weeks ago
Your Name 742c1a6bc8 Require dangerzone sudo mode on curated register, shadow filter and page admin controllers 2 weeks ago
Shlee 97b5d2f180
Merge pull request #7159 from shleeable/fix/directory-exclude-private-profiles
Exclude private profiles from public directory and clear suggestable on going private
2 weeks ago
Your Name 1581863093 Exclude private profiles from public directory and clear suggestable on going private 2 weeks ago
Shlee 903c191f10
Merge pull request #7158 from shleeable/fix/2fa-logout-session-cleanup
Clear 2FA session state on forced logout after failed attempts
2 weeks ago
Your Name 97f1a097ff Clear 2FA session state on forced logout after failed attempts 2 weeks ago
Shlee eaadf425f2
Merge pull request #7157 from shleeable/fix/dangerzone-oidc-per-user
Scope DangerZone OIDC sudo bypass to OIDC-registered users
2 weeks ago
Your Name 7483a4b05b Scope DangerZone OIDC sudo bypass to OIDC-registered users 2 weeks ago