Commit Graph

378 Commits (933e24c9bade0d1f4aac3ed0f4e3411aec2f7bb7)

Author SHA1 Message Date
Shlee 9ec46005df
Merge pull request #7309 from pixelfed/feature/laravel-cap
Refactor: Captcha provider - HCaptcha, Turnstile and Cap
1 week ago
Your Name b24503a46c chore: rename Pirate English locale to BCP-47 en-x-pirate
Use the BCP-47 private-use subtag en-x-pirate instead of en-Pirate:
- rename lang/en-Pirate -> lang/en-x-pirate
- update crowdin.yml mapping (en-PT -> en-x-pirate)
- update ExportLanguages LOCALE_OVERRIDES key + display name
- bump locale code validation max length (6 -> 12) so the longer
  code passes in SpaController and HomeSettings
- regenerate locale exports/manifest and rebuild web assets
1 week ago
Your Name 337de5a64e fix pirate 1 week ago
Shlee 2d65095f9a
Update ExportLanguages.php 1 week ago
Your Name 7d84856da3 polish 1 week ago
Your Name fcea9dc34b polish 1 week ago
Your Name 6f78c1d976 polish 1 week ago
Your Name 8f4add2f1e polish 1 week ago
Your Name 054d129479 fix(i18n): skip empty translation strings in i18n:export
Empty lang/x/web.php values (untranslated Crowdin placeholders) were
being exported as empty strings, overriding the English UI fallback and
breaking non-English languages. Recursively strip empty strings before
writing the JSON build files, then regenerate all language files.
1 week ago
Your Name 648a901aae polish 1 week ago
Daniel Supernault 31c652427f
Remove deprecated command 1 week ago
Daniel Supernault 68b1a55960
Update Instagram Imports 1 week ago
Daniel Supernault 83c9b86ae3
Add AccountRevocationService 1 week 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.
1 week 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).
1 week ago
Daniel Supernault 22108f8f11
Lint PostImportController 1 week ago
Daniel Supernault 7a98ebfe56
Delete NotificationEpochUpdate.php 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 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
Daniel Supernault 6ddc803ae1
Fix SoftwareUpdate notices 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
Your Name e360fab619 Deterministically keep earliest status per uri in dedupe command 2 weeks ago
Your Name 327348be02 Send Pixelfed User-Agent on federated account deletion deliveries 2 weeks ago
Your Name a1724a4b1c Scope reclaim-username profile deletion and fail on surviving orphan 2 weeks ago
Daniel Supernault f37c5fc95c
Add notification gc 2 weeks ago
Daniel Supernault 896342a57f
Update MediaMoveStorageLocalToCloud.php 2 weeks ago
Daniel Supernault 764a98437d
Fix media gc 2 weeks ago
Daniel Supernault 85fec3ac82
Create PruneOldNotifications.php 2 weeks ago
Your Name 042ab0a6e4 Convert optional() to nullsafe operator
Applies patch 2/21 from pixelfed-staging PR #9: replaces optional($x)->y
with $x?->y across 16 files. Pint-clean.
3 weeks ago
Your Name 9db2218ca6 chore: move resources/lang to top-level lang/ per Laravel 9+ convention
- Relocate translation files from resources/lang to lang/ via git mv
- Update PHP references to use the lang_path() helper
- Update crowdin.yml source/translation paths
- Update phpstan.neon translationDirectories
3 weeks ago
Your Name b8ca4da3a6 Add per-file transfer output and --debug detail to MediaMoveStorageLocalToCloud 3 weeks ago
Your Name 6b14b229d1 Fix media storage migration crash when no .env file exists
The media storage migration commands read/parsed the .env file directly to
check and flip PF_ENABLE_CLOUD. In containerized deploys there is no .env on
disk (config is injected via env vars), so updateEnvFile() threw
'file_get_contents(.env): Failed to open stream' and the scheduled command
exited 1.

- Check the live setting via config_cache('pixelfed.cloud_storage') like the
  rest of the app, instead of parsing .env.
- Make the .env write best-effort in ManagesMediaStorageEnv: skip gracefully
  when the file is missing or read-only, and still apply the runtime + DB
  config-cache updates (the load-bearing changes on a hot server).
- Apply the same fix to the sibling unstable:MediaMoveStorageCloudToLocal.
- Add a regression test covering the no-.env container scenario.
3 weeks ago
Shlee 8dafe75567
Merge pull request #6992 from pixelfed/feat/status-inspector-commands
Feat/status inspector commands
3 weeks ago
Your Name 9888923a84 Add status:instance, status:avatar, status:emoji inspector commands
Diagnostic commands mirroring status:statuses/status:media:
- status:instance {id|domain|url|@user@domain}: instance row, moderation
  state (banned/unlisted/auto_cw), sync timestamps, local profile count.
- status:avatar {avatar_id|profile_id} [--check]: avatar row, storage state
  (local/cloud existence), owning profile, optional live HEAD on remote_url.
- status:emoji {id|:shortcode:|filename} [--check]: emoji row, origin
  (local/remote), local file existence, optional live HEAD on image_remote_url.

Also includes the status:post -> status:statuses rename.
3 weeks ago
Your Name 237ed61b5d Rename status:post to status:statuses
Rename command signature (status:post -> status:statuses), class
(StatusPost -> StatusStatuses), and file to match.
3 weeks ago
Your Name d62c589881 Rename media:maintenance to media:filtercleanup
Rename the command signature (media:maintenance -> media:filtercleanup), class
(MediaMaintenance -> MediaFilterCleanup), and file to match. Behavior
unchanged.
3 weeks ago
Your Name 4dfb34de75 Drop live from --status on media:maintenance
Orphaned media never references a live status, so --status only accepts soft
and hard. --profile still accepts live/soft/hard. Removes the now-redundant
live short-circuit and makes valid values per-option.
3 weeks ago
Your Name 4ad6e91ef9 Add --status and --profile state filters to media:maintenance
--status live|soft|hard and --profile live|soft|hard narrow orphaned media by
the lifecycle state of the referenced status/profile row. Filters are applied
at the SQL level (whereExists/whereNotExists on deleted_at) so they compose
correctly with --limit. --status=live short-circuits since orphaned media never
has a live status. Options are validated up front.
3 weeks ago
Your Name 838a6b999c Add TODO.md; enhance media:maintenance with --server filter and state annotations
- TODO.md: capture follow-ups (centralized status media teardown, DM leak fix,
  no-DB-cascade rationale, remote-edit orphaning, media:gc re-check).
- media:maintenance: add --server remote|local|both (default both) to filter
  orphaned media by origin.
- Annotate each row with status state (live/soft-deleted/hard-deleted) next to
  status_id and profile state (live/soft-deleted/hard-deleted) next to
  profile_id, in both dry-run table and verbose run output. States are resolved
  in batched, trashed-aware queries.
3 weeks ago
Your Name 48a1fe5e5e Add verbose output to media:maintenance
With -v, print per-row detail (media_id, original status_id, remote_media,
profile_id, mime, size, path) as each orphaned row is processed instead of the
progress bar, and expand the dry-run table with extra columns. Uses Laravel's
built-in verbosity flag.
3 weeks ago
Your Name 87dad44d09 Add media:maintenance command with orphanedMedia scope
media:maintenance --scope orphanedMedia cleans up media whose status_id
references a status that no longer exists (hard-deleted) or is soft-deleted.
These dangling references predate the delete-path fix and MediaDeletePipeline's
attached guard would otherwise refuse to delete them, leaking files.

Detaches (status_id = null) before dispatching deletion via MediaStorageService,
so the guard sees a genuinely orphaned row. Supports --limit (batched),
--dry-run, and --force. The --scope map is extensible for future routines.
3 weeks ago
Your Name 69869536a1 Fix remote status deletion leaking attached media, add status:media command
MediaDeletePipeline skips deletion when media->status_id is set. status_id has
no FK/cascade, so deleting a status never clears it, and the delete jobs
dispatched by the status-delete paths were always skipped, leaking media files.

Detach media (status_id = null) before dispatching the delete in StatusDelete,
RemoteStatusDelete and DeleteRemoteStatusPipeline, so the row is genuinely
orphaned by the time the guard checks it and the deletion proceeds.

Also adds a status:media diagnostic command that dumps all metadata for a
media id (DB columns, computed URLs, attachment state, parent status including
the dangling status_id case, owner, metadata, and an optional live URL check).
3 weeks ago
Your Name 9214e9680a Add admin:resyncemoji command to re-download remote emoji locally
Adds CustomEmojiService::resync() which re-fetches a remote custom emoji's
media from its origin (image_remote_url) via the SSRF-hardened
SecureMediaFetchService and stores it locally under public/{media_path},
reusing the existing headCheck validation and cache busting.

The admin:resyncemoji command takes a comma-separated list of emoji
filenames, looks each up by media_path, and resyncs remote ones. Supports
--missingonly, --dry-run and --force.
3 weeks ago
Your Name fce75030e0 refactor: simplify storage:maintenance flags and make it quiet by default
- Drop --except (--only already covers task selection)
- Quiet by default; per-root/per-item and summary lines now require -v/--verbose
- Errors are always shown regardless of verbosity
- Document the command in the console README
3 weeks ago
Your Name 8ca3ac4dcc polish 3 weeks ago
Your Name 400f00c5e1 feat: storage:maintenance command + in-flow cleanup of emptied dirs
Replace the remcache GC (GarbageCollectorRemcache / gc:remcache) with a
broader storage:maintenance command that sweeps stale remcache temp files and
recursively removes the random empty directories accumulated under the media,
story, avatar and import trees (--hours/--only/--except/--dry-run), scheduled
daily.

Fix the root causes so flows clean up after themselves rather than relying on
the sweep:
- MediaDeletePipeline removes its own emptied m/_v2 leaf dir
- AvatarOptimize logs the previously-swallowed exception, still cleans up the
  old avatar on failure, and removes the old file's now-empty splayed dir
- AvatarController::deleteAvatar removes the emptied splayed dir
- StoryExpire/StoryDelete remove the story's own emptied leaf dir
- TransformImports removes imports/{userId} once its files are moved out
- StoryFetch cleans up its remcache temp file in a finally block
3 weeks ago