Skip to content

Commit b094f5d

Browse files
committed
Fix issues with delete expedition and flash messaging.
1 parent 8cbc7c1 commit b094f5d

File tree

7 files changed

+141
-66
lines changed

7 files changed

+141
-66
lines changed

app/Http/Middleware/EncryptCookies.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ class EncryptCookies extends Middleware
3030
* @var array
3131
*/
3232
protected $except = [
33-
//
33+
'app_flash',
3434
];
3535
}
Lines changed: 34 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22

33
/*
4-
* Copyright (C) 2014 - 2025, Biospex
4+
* Copyright (C) 2014 - 2026, Biospex
55
66
*
77
* This program is free software: you can redistribute it and/or modify
@@ -22,7 +22,6 @@
2222

2323
use Closure;
2424
use Illuminate\Http\Request;
25-
use JavaScript;
2625

2726
class FlashHelperMessage
2827
{
@@ -31,72 +30,46 @@ class FlashHelperMessage
3130
*/
3231
public function handle(Request $request, Closure $next): mixed
3332
{
34-
$message = [
35-
'flashType' => '',
36-
'flashMessage' => '',
37-
'flashIcon' => '',
38-
];
39-
40-
$status = ['success', 'info', 'warning', 'danger'];
41-
if (session()->hasAny('success', 'info', 'warning', 'danger')) {
42-
foreach ($status as $type) {
43-
if (session()->has($type)) {
44-
$message['flashType'] = $type;
45-
$message['flashMessage'] = session($type);
46-
$message['flashIcon'] = match ($type) {
47-
'success' => 'check-circle',
48-
'info' => 'info-circle',
49-
'warning' => 'exclamation-circle',
50-
'danger' => 'times-circle',
51-
};
52-
break;
53-
}
54-
}
33+
// If there's a flash message, tell the Cache middleware (running next) to skip this request
34+
if (session()->hasAny(['success', 'info', 'warning', 'danger'])) {
35+
$request->attributes->set('laravel-responsecache.do-not-cache', true);
5536
}
5637

57-
JavaScript::put($message);
38+
$response = $next($request);
5839

59-
return $next($request);
60-
}
40+
if ($request->isMethod('GET')) {
41+
$status = ['success', 'info', 'warning', 'danger'];
6142

62-
private function create($message, $type, $icon)
63-
{
64-
session()->flash('flash_message', [
65-
'type' => $type,
66-
'message' => $message,
67-
'icon' => $icon,
68-
]);
69-
}
43+
foreach ($status as $type) {
44+
if (session()->has($type)) {
45+
// 2. Also set the header on the outgoing response for safety
46+
$response->headers->set('laravel-responsecache', 'do-not-cache');
7047

71-
/**
72-
* Create success message.
73-
*/
74-
public function success($message)
75-
{
76-
$this->create($message, 'success', 'check-circle');
77-
}
48+
$payload = json_encode([
49+
'type' => $type,
50+
'message' => (string) session($type),
51+
'icon' => match ($type) {
52+
'success' => 'check-circle',
53+
'info' => 'info-circle',
54+
'warning' => 'exclamation-circle',
55+
'danger' => 'times-circle',
56+
default => 'info-circle',
57+
},
58+
]);
7859

79-
/**
80-
* Create info message.
81-
*/
82-
public function info($message)
83-
{
84-
$this->create($message, 'info', 'info-circle');
85-
}
60+
// Create a simple session cookie (minutes=0)
61+
// No domain, No secure (for local testing), No httpOnly
62+
$response->withCookie(cookie('app_flash', $payload, 0, '/', null, false, false, false, 'Lax'));
8663

87-
/**
88-
* Create warning message.
89-
*/
90-
public function warning($message)
91-
{
92-
$this->create($message, 'warning', 'exclamation-circle');
93-
}
64+
session()->forget($type);
9465

95-
/**
96-
* Create danger message.
97-
*/
98-
public function error($message)
99-
{
100-
$this->create($message, 'danger', 'times-circle');
66+
// Forget the session key so it doesn't persist
67+
session()->forget($type);
68+
break;
69+
}
70+
}
71+
}
72+
73+
return $response;
10174
}
10275
}

app/Jobs/DeleteExpeditionJob.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,19 @@ public function handle(
6161
$this->expedition->load('downloads');
6262

6363
$this->expedition->downloads->each(function ($download) {
64-
Storage::disk('s3')->delete(config('config.export_dir').'/'.$download->file);
64+
$path = config('config.export_dir').'/'.$download->file;
65+
66+
try {
67+
// We check existence to avoid unnecessary API calls,
68+
// but we catch the failure because S3 consistency is not guaranteed.
69+
if (Storage::disk('s3')->exists($path)) {
70+
Storage::disk('s3')->delete($path);
71+
}
72+
} catch (\Throwable $e) {
73+
// If the file is already gone or inaccessible, we continue.
74+
// This prevents the "UnableToDeleteFile" exception from failing the job.
75+
\Log::warning('S3 Delete failed but continuing: '.$path);
76+
}
6577
});
6678

6779
$mongoDbService->setCollection('pusher_transcriptions');
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
/*
4+
* Copyright (C) 2014 - 2026, Biospex
5+
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
namespace App\Services\Cache;
22+
23+
use Spatie\ResponseCache\Replacers\Replacer;
24+
use Symfony\Component\HttpFoundation\Response;
25+
26+
class FlashReplacer implements Replacer
27+
{
28+
public function prepareResponseToCache(Response $response): void
29+
{
30+
// No-op: We don't want to store anything special in the cached HTML
31+
}
32+
33+
public function replaceInCachedResponse(Response $response): void
34+
{
35+
$status = ['success', 'info', 'warning', 'danger'];
36+
37+
foreach ($status as $type) {
38+
if (session()->has($type)) {
39+
$payload = json_encode([
40+
'type' => $type,
41+
'message' => (string) session($type),
42+
'icon' => match ($type) {
43+
'success' => 'check-circle',
44+
'info' => 'info-circle',
45+
'warning' => 'exclamation-circle',
46+
'danger' => 'times-circle',
47+
default => 'info-circle',
48+
},
49+
]);
50+
51+
// Ensure the cookie is set correctly
52+
$response->headers->setCookie(cookie('app_flash', $payload, 0, '/', null, false, false, false, 'Lax'));
53+
54+
// Do not cache the response that contains the cookie header
55+
$response->headers->set('laravel-responsecache', 'do-not-cache');
56+
57+
session()->forget($type);
58+
break;
59+
}
60+
}
61+
}
62+
}

config/filesystems.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,21 @@
4848
'driver' => 's3',
4949
'key' => env('AWS_ACCESS_KEY_ID'),
5050
'secret' => env('AWS_SECRET_ACCESS_KEY'),
51-
'region' => env('AWS_DEFAULT_REGION', 'us-east-2'),
52-
'bucket' => env('AWS_BUCKET', 'biospex-loc'),
51+
'region' => env('AWS_DEFAULT_REGION'),
52+
'bucket' => env('AWS_BUCKET'),
5353
'url' => env('AWS_URL'),
5454
'endpoint' => env('AWS_ENDPOINT'),
5555
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
5656
'throw' => true,
57-
'visibility' => 'private',
57+
'options' => [
58+
'credentials' => [
59+
// Use the file on local/WSL2 if it exists, otherwise fall back to default (Roles)
60+
'file' => file_exists('/home/ubuntu/.aws/credentials')
61+
? '/home/ubuntu/.aws/credentials'
62+
: null,
63+
'profile' => 'default',
64+
],
65+
],
5866
],
5967
'efs' => [
6068
'driver' => 'local',

config/responsecache.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
*/
9191
'replacers' => [
9292
\Spatie\ResponseCache\Replacers\CsrfTokenReplacer::class,
93+
\App\Services\Cache\FlashReplacer::class,
9394
],
9495

9596
/*

resources/js/common.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,25 @@ $(function () {
158158
$(this).toggleClass("is-active");
159159
});
160160

161+
const flashCookie = document.cookie.split('; ').find(row => row.startsWith('app_flash='));
162+
if (flashCookie) {
163+
try {
164+
const rawValue = decodeURIComponent(flashCookie.split('=')[1]);
165+
const data = JSON.parse(rawValue);
166+
167+
if (data && data.message) {
168+
notify(data.icon, data.message, data.type);
169+
}
170+
171+
// Force delete by matching the path and ensuring no domain conflict
172+
document.cookie = "app_flash=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
173+
// Extra safety: Try to delete the dotted domain version too if it exists
174+
document.cookie = "app_flash=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=" + window.location.hostname + ";";
175+
document.cookie = "app_flash=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=." + window.location.hostname + ";";
176+
} catch (e) {
177+
console.error("Flash cookie error", e);
178+
}
179+
}
161180

162181
if (Laravel.flashMessage.length) {
163182
notify(Laravel.flashIcon, Laravel.flashMessage, Laravel.flashType);

0 commit comments

Comments
 (0)