Skip to content

Commit 48df872

Browse files
committed
Added better drawing load failure handling
Failure of loading drawings will now close the drawing view and show an error message, hinting at file or permission issues, instead of leaving the user facing a continuosly loading interface. Adds test to cover. This also updates errors from our HTTP service to be wrapped in a custom error type for better identification and so the error is an actual javascript error. Should be object compatible. Related to #3955.
1 parent 25bdd71 commit 48df872

File tree

7 files changed

+79
-18
lines changed

7 files changed

+79
-18
lines changed

app/Http/Controllers/Images/DrawioImageController.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,19 @@ public function create(Request $request)
6666
*/
6767
public function getAsBase64($id)
6868
{
69-
$image = $this->imageRepo->getById($id);
70-
if (is_null($image) || $image->type !== 'drawio' || !userCan('page-view', $image->getPage())) {
71-
return $this->jsonError('Image data could not be found');
69+
try {
70+
$image = $this->imageRepo->getById($id);
71+
} catch (Exception $exception) {
72+
return $this->jsonError(trans('errors.drawing_data_not_found'), 404);
73+
}
74+
75+
if ($image->type !== 'drawio' || !userCan('page-view', $image->getPage())) {
76+
return $this->jsonError(trans('errors.drawing_data_not_found'), 404);
7277
}
7378

7479
$imageData = $this->imageRepo->getImageData($image);
7580
if (is_null($imageData)) {
76-
return $this->jsonError('Image data could not be found');
81+
return $this->jsonError(trans('errors.drawing_data_not_found'), 404);
7782
}
7883

7984
return response()->json([

resources/js/services/drawio.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,16 @@ async function upload(imageData, pageUploadedToId) {
9595
* @returns {Promise<string>}
9696
*/
9797
async function load(drawingId) {
98-
const resp = await window.$http.get(window.baseUrl(`/images/drawio/base64/${drawingId}`));
99-
return `data:image/png;base64,${resp.data.content}`;
98+
try {
99+
const resp = await window.$http.get(window.baseUrl(`/images/drawio/base64/${drawingId}`));
100+
return `data:image/png;base64,${resp.data.content}`;
101+
} catch (error) {
102+
if (error instanceof window.$http.HttpError) {
103+
window.$events.showResponseError(error);
104+
}
105+
close();
106+
throw error;
107+
}
100108
}
101109

102110
export default {show, close, upload, load};

resources/js/services/events.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,8 @@ function emitPublic(targetElement, eventName, eventData) {
4343
}
4444

4545
/**
46-
* Notify of a http error.
47-
* Check for standard scenarios such as validation errors and
48-
* formats an error notification accordingly.
49-
* @param {Error} error
46+
* Notify of standard server-provided validation errors.
47+
* @param {Object} error
5048
*/
5149
function showValidationErrors(error) {
5250
if (!error.status) return;
@@ -56,11 +54,23 @@ function showValidationErrors(error) {
5654
}
5755
}
5856

57+
/**
58+
* Notify standard server-provided error messages.
59+
* @param {Object} error
60+
*/
61+
function showResponseError(error) {
62+
if (!error.status) return;
63+
if (error.status >= 400 && error.data && error.data.message) {
64+
emit('error', error.data.message);
65+
}
66+
}
67+
5968
export default {
6069
emit,
6170
emitPublic,
6271
listen,
6372
success: (msg) => emit('success', msg),
6473
error: (msg) => emit('error', msg),
6574
showValidationErrors,
75+
showResponseError,
6676
}

resources/js/services/http.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ async function request(url, options = {}) {
132132
};
133133

134134
if (!response.ok) {
135-
throw returnData;
135+
throw new HttpError(response, content);
136136
}
137137

138138
return returnData;
@@ -159,10 +159,24 @@ async function getResponseContent(response) {
159159
return await response.text();
160160
}
161161

162+
class HttpError extends Error {
163+
constructor(response, content) {
164+
super(response.statusText);
165+
this.data = content;
166+
this.headers = response.headers;
167+
this.redirected = response.redirected;
168+
this.status = response.status;
169+
this.statusText = response.statusText;
170+
this.url = response.url;
171+
this.original = response;
172+
}
173+
}
174+
162175
export default {
163176
get: get,
164177
post: post,
165178
put: put,
166179
patch: patch,
167180
delete: performDelete,
181+
HttpError: HttpError,
168182
};

resources/js/wysiwyg/plugin-drawio.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ function drawingInit() {
8989
return Promise.resolve('');
9090
}
9191

92-
let drawingId = currentNode.getAttribute('drawio-diagram');
92+
const drawingId = currentNode.getAttribute('drawio-diagram');
9393
return DrawIO.load(drawingId);
9494
}
9595

resources/lang/en/errors.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,12 @@
4545
'cannot_create_thumbs' => 'The server cannot create thumbnails. Please check you have the GD PHP extension installed.',
4646
'server_upload_limit' => 'The server does not allow uploads of this size. Please try a smaller file size.',
4747
'uploaded' => 'The server does not allow uploads of this size. Please try a smaller file size.',
48+
'file_upload_timeout' => 'The file upload has timed out.',
49+
50+
// Drawing & Images
4851
'image_upload_error' => 'An error occurred uploading the image',
4952
'image_upload_type_error' => 'The image type being uploaded is invalid',
50-
'file_upload_timeout' => 'The file upload has timed out.',
53+
'drawing_data_not_found' => 'Drawing data could not be loaded. The drawing file might no longer exist or you may not have permission to access it.',
5154

5255
// Attachments
5356
'attachment_not_found' => 'Attachment not found',

tests/Uploads/DrawioTest.php

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ class DrawioTest extends TestCase
1212

1313
public function test_get_image_as_base64()
1414
{
15-
$page = Page::first();
15+
$page = $this->entities->page();
1616
$this->asAdmin();
1717
$imageName = 'first-image.png';
1818

1919
$this->uploadImage($imageName, $page->id);
20-
$image = Image::first();
20+
/** @var Image $image */
21+
$image = Image::query()->first();
2122
$image->type = 'drawio';
2223
$image->save();
2324

@@ -27,9 +28,29 @@ public function test_get_image_as_base64()
2728
]);
2829
}
2930

31+
public function test_non_accessible_image_returns_404_error_and_message()
32+
{
33+
$page = $this->entities->page();
34+
$this->asEditor();
35+
$imageName = 'non-accessible-image.png';
36+
37+
$this->uploadImage($imageName, $page->id);
38+
/** @var Image $image */
39+
$image = Image::query()->first();
40+
$image->type = 'drawio';
41+
$image->save();
42+
$this->permissions->disableEntityInheritedPermissions($page);
43+
44+
$imageGet = $this->getJson("/images/drawio/base64/{$image->id}");
45+
$imageGet->assertNotFound();
46+
$imageGet->assertJson([
47+
'message' => 'Drawing data could not be loaded. The drawing file might no longer exist or you may not have permission to access it.',
48+
]);
49+
}
50+
3051
public function test_drawing_base64_upload()
3152
{
32-
$page = Page::first();
53+
$page = $this->entities->page();
3354
$editor = $this->users->editor();
3455
$this->actingAs($editor);
3556

@@ -57,7 +78,7 @@ public function test_drawing_base64_upload()
5778
public function test_drawio_url_can_be_configured()
5879
{
5980
config()->set('services.drawio', 'http://cats.com?dog=tree');
60-
$page = Page::first();
81+
$page = $this->entities->page();
6182
$editor = $this->users->editor();
6283

6384
$resp = $this->actingAs($editor)->get($page->getUrl('/edit'));
@@ -67,7 +88,7 @@ public function test_drawio_url_can_be_configured()
6788
public function test_drawio_url_can_be_disabled()
6889
{
6990
config()->set('services.drawio', true);
70-
$page = Page::first();
91+
$page = $this->entities->page();
7192
$editor = $this->users->editor();
7293

7394
$resp = $this->actingAs($editor)->get($page->getUrl('/edit'));

0 commit comments

Comments
 (0)