Repository navigation
feat: attach images to commit reports #1112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
xHeaven
merged 16 commits into
dev-null-sh:production
from
sheraz4196:fix/982-issue-image-attachments
Oct 30, 2026
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
494db37
feat: store private image attachments on commit reports
sheraz4196 27706d5
feat: attach images from commit report dialogs
sheraz4196 c27363e
merge: resolve production conflicts in report attachments
sheraz4196 4dfad91
merge: preserve report attachments with latest production
sheraz4196 12a586c
fix: release report attachment preview URLs
sheraz4196 407140e
merge: sync image attachments branch with production
sheraz4196 a75da44
merge: sync production and preserve user deletion coverage
sheraz4196 f89d76a
fix: serialize report attachments with account deletion
sheraz4196 1ecc4c0
fix: retain account file cleanup for durable retries
sheraz4196 ec4a48f
fix: roll back reports when attachment storage fails
sheraz4196 436d034
fix: disable report attachments while submitting
sheraz4196 86545c2
fix: validate retained file cleanup records
sheraz4196 1714617
fix: remove ineffective global exception import
sheraz4196 980c2f3
test: cover image storage failures
sheraz4196 f530e5c
test: cover malformed file cleanup records
sheraz4196 46bdbc7
Merge branch 'production' into fix/982-issue-image-attachments
xHeaven File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace App\Actions; | ||
|
|
||
| use Illuminate\Support\Facades\DB; | ||
| use Illuminate\Support\Facades\Storage; | ||
| use RuntimeException; | ||
| use Throwable; | ||
| use UnexpectedValueException; | ||
|
|
||
| final readonly class DeleteStoredFiles | ||
| { | ||
| /** | ||
| * Call inside the transaction removing the file metadata. The cleanup survives a crash after commit, | ||
| * and rolls back with the metadata if deletion of the account fails. | ||
| * | ||
| * @param array<int, string> $paths | ||
| */ | ||
| public function retain(array $paths): void | ||
| { | ||
| if ($paths === []) { | ||
| return; | ||
| } | ||
|
|
||
| $id = DB::table('pending_file_deletions')->insertGetId([ | ||
| 'disk' => config()->string('filesystems.default'), | ||
| 'paths' => json_encode(array_values(array_unique($paths)), JSON_THROW_ON_ERROR), | ||
| ]); | ||
|
|
||
| DB::afterCommit(fn () => $this->handle($id)); | ||
| } | ||
|
|
||
| public function handle(int $id): void | ||
| { | ||
| $pending = DB::table('pending_file_deletions')->find($id); | ||
|
|
||
| if ($pending === null) { | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| if (! is_object($pending) | ||
| || ! isset($pending->paths, $pending->disk) | ||
| || ! is_string($pending->paths) | ||
| || ! is_string($pending->disk)) { | ||
| throw new UnexpectedValueException('Invalid pending file deletion record '.$id); | ||
| } | ||
|
|
||
| $decodedPaths = json_decode($pending->paths, true, flags: JSON_THROW_ON_ERROR); | ||
|
|
||
| if (! is_array($decodedPaths) || ! array_is_list($decodedPaths)) { | ||
| throw new UnexpectedValueException('Invalid paths for pending file deletion '.$id); | ||
| } | ||
|
|
||
| $paths = []; | ||
| foreach ($decodedPaths as $path) { | ||
| if (! is_string($path)) { | ||
| throw new UnexpectedValueException('Invalid path for pending file deletion '.$id); | ||
| } | ||
|
|
||
| $paths[] = $path; | ||
| } | ||
|
|
||
| if (! Storage::disk($pending->disk)->delete($paths)) { | ||
| throw new RuntimeException('File cleanup failed for pending deletion '.$id); | ||
| } | ||
|
|
||
| DB::table('pending_file_deletions')->where('id', $id)->delete(); | ||
| } catch (Throwable $throwable) { | ||
| // Keep the durable record for the scheduled retry, including when the disk throws. | ||
| report($throwable); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace App\Http\Controllers; | ||
|
|
||
| use App\Http\Requests\ShowCommitReportImageRequest; | ||
| use App\Models\CommitReport; | ||
| use App\Services\EncryptedFiles; | ||
| use Illuminate\Http\Response; | ||
| use Illuminate\Support\Facades\Storage; | ||
|
|
||
| final readonly class CommitReportImageController | ||
| { | ||
| public function show(ShowCommitReportImageRequest $request, CommitReport $report, int $image, EncryptedFiles $encryptedFiles): Response | ||
| { | ||
| $file = $report->images[$image] ?? null; | ||
| assert(is_array($file)); | ||
|
|
||
| return response($encryptedFiles->decrypt((string) Storage::disk()->get($file['path'])), headers: [ | ||
| 'Content-Type' => 'image/webp', | ||
| 'Content-Disposition' => 'inline', | ||
| 'Content-Security-Policy' => "default-src 'none'; sandbox", | ||
| 'X-Content-Type-Options' => 'nosniff', | ||
| 'Cache-Control' => 'private, no-store', | ||
| ]); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.