mirror of
https://github.com/grocy/grocy.git
synced 2026-07-06 14:12:18 -07:00
Route all file requests through FilesApiController/ServeFile
This commit is contained in:
@@ -47,45 +47,25 @@ class FilesApiController extends BaseApiController
|
||||
throw new \Exception('Invalid file group');
|
||||
}
|
||||
|
||||
$fileName = $this->CheckFileName($args['fileName']);
|
||||
$filePath = $this->GetFilePath($args['group'], $fileName, $request->getQueryParams());
|
||||
|
||||
if (file_exists($filePath))
|
||||
if (str_contains($args['fileName'], '_'))
|
||||
{
|
||||
$response = $response->withHeader('Cache-Control', 'max-age=2592000');
|
||||
$response = $response->withHeader('Content-Type', mime_content_type($filePath));
|
||||
$response = $response->withHeader('Content-Disposition', 'inline; filename="' . $fileName . '"');
|
||||
return $response->withBody(new Stream(fopen($filePath, 'rb')));
|
||||
$fileInfo = explode('_', $args['fileName']);
|
||||
$fileName = $this->CheckFileName($fileInfo[0]);
|
||||
$fileNameOutput = $this->CheckFileName($fileInfo[1]);
|
||||
$filePath = $this->GetFilePath($args['group'], $fileName, $request->getQueryParams());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new HttpNotFoundException($request, 'File not found');
|
||||
$fileName = $this->CheckFileName($args['fileName']);
|
||||
$fileNameOutput = $fileName;
|
||||
$filePath = $this->GetFilePath($args['group'], $fileName, $request->getQueryParams());
|
||||
}
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
throw new HttpNotFoundException($request, $ex->getMessage(), $ex);
|
||||
}
|
||||
}
|
||||
|
||||
public function ShowFile(Request $request, Response $response, array $args)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!in_array($args['group'], $this->GetOpenApispec()->components->schemas->FileGroups->enum))
|
||||
{
|
||||
throw new \Exception('Invalid file group');
|
||||
}
|
||||
|
||||
$fileInfo = explode('_', $args['fileName']);
|
||||
$fileName = $this->CheckFileName($fileInfo[1]);
|
||||
$filePath = $this->GetFilePath($args['group'], base64_decode($fileInfo[0]), $request->getQueryParams());
|
||||
|
||||
if (file_exists($filePath))
|
||||
{
|
||||
$response = $response->withHeader('Cache-Control', 'max-age=2592000');
|
||||
$response = $response->withHeader('Content-Type', mime_content_type($filePath));
|
||||
$response = $response->withHeader('Content-Disposition', 'inline; filename="' . $fileName . '"');
|
||||
$response = $response->withHeader('Content-Disposition', 'inline; filename="' . $fileNameOutput . '"');
|
||||
return $response->withBody(new Stream(fopen($filePath, 'rb')));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Grocy.Components.UserfieldsForm = {};
|
||||
|
||||
Grocy.Components.UserfieldsForm.Save = function(success, error)
|
||||
Grocy.Components.UserfieldsForm.Save = function (success, error)
|
||||
{
|
||||
if (!$("#userfields-form").length)
|
||||
{
|
||||
@@ -24,7 +24,7 @@ Grocy.Components.UserfieldsForm.Save = function(success, error)
|
||||
return;
|
||||
}
|
||||
|
||||
editedUserfieldInputs.each(function(index, item)
|
||||
editedUserfieldInputs.each(function (index, item)
|
||||
{
|
||||
var jsonData = {};
|
||||
var input = $(this);
|
||||
@@ -68,22 +68,22 @@ Grocy.Components.UserfieldsForm.Save = function(success, error)
|
||||
}
|
||||
|
||||
Grocy.Api.Put('userfields/' + $("#userfields-form").data("entity") + '/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
function (result)
|
||||
{
|
||||
if (typeof newFile !== 'undefined' && typeof oldFile !== 'undefined') // Delete and Upload
|
||||
{
|
||||
Grocy.Api.DeleteFile(oldFile, 'userfiles',
|
||||
function(result)
|
||||
function (result)
|
||||
{
|
||||
Grocy.Api.UploadFile(input[0].files[0], 'userfiles', newFile,
|
||||
function(result2)
|
||||
function (result2)
|
||||
{
|
||||
if (success && index === editedUserfieldInputs.length - 1) // Last item
|
||||
{
|
||||
success();
|
||||
}
|
||||
},
|
||||
function(xhr)
|
||||
function (xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response);
|
||||
if (error && index === editedUserfieldInputs.length - 1) // Last item
|
||||
@@ -93,7 +93,7 @@ Grocy.Components.UserfieldsForm.Save = function(success, error)
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
function (xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response);
|
||||
if (error && index === editedUserfieldInputs.length - 1) // Last item
|
||||
@@ -106,14 +106,14 @@ Grocy.Components.UserfieldsForm.Save = function(success, error)
|
||||
else if (typeof newFile !== 'undefined') // Upload only
|
||||
{
|
||||
Grocy.Api.UploadFile(input[0].files[0], 'userfiles', newFile,
|
||||
function(result2)
|
||||
function (result2)
|
||||
{
|
||||
if (success && index === editedUserfieldInputs.length - 1) // Last item
|
||||
{
|
||||
success();
|
||||
}
|
||||
},
|
||||
function(xhr)
|
||||
function (xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response);
|
||||
if (error && index === editedUserfieldInputs.length - 1) // Last item
|
||||
@@ -126,14 +126,14 @@ Grocy.Components.UserfieldsForm.Save = function(success, error)
|
||||
else if (typeof oldFile !== 'undefined') // Delete only
|
||||
{
|
||||
Grocy.Api.DeleteFile(oldFile, 'userfiles',
|
||||
function(result)
|
||||
function (result)
|
||||
{
|
||||
if (success && index === editedUserfieldInputs.length - 1) // Last item
|
||||
{
|
||||
success();
|
||||
}
|
||||
},
|
||||
function(xhr)
|
||||
function (xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response);
|
||||
if (error && index === editedUserfieldInputs.length - 1) // Last item
|
||||
@@ -151,7 +151,7 @@ Grocy.Components.UserfieldsForm.Save = function(success, error)
|
||||
}
|
||||
}
|
||||
},
|
||||
function(xhr)
|
||||
function (xhr)
|
||||
{
|
||||
if (error && index === editedUserfieldInputs.length - 1) // Last item
|
||||
{
|
||||
@@ -162,7 +162,7 @@ Grocy.Components.UserfieldsForm.Save = function(success, error)
|
||||
});
|
||||
}
|
||||
|
||||
Grocy.Components.UserfieldsForm.Load = function()
|
||||
Grocy.Components.UserfieldsForm.Load = function ()
|
||||
{
|
||||
if (!$("#userfields-form").length)
|
||||
{
|
||||
@@ -174,9 +174,9 @@ Grocy.Components.UserfieldsForm.Load = function()
|
||||
// Init fields by configured default values
|
||||
|
||||
Grocy.Api.Get("objects/userfields?query[]=entity=" + $("#userfields-form").data("entity"),
|
||||
function(result)
|
||||
function (result)
|
||||
{
|
||||
$.each(result, function(key, userfield)
|
||||
$.each(result, function (key, userfield)
|
||||
{
|
||||
var input = $(".userfield-input[data-userfield-name='" + userfield.name + "']");
|
||||
|
||||
@@ -191,19 +191,19 @@ Grocy.Components.UserfieldsForm.Load = function()
|
||||
else if (userfield.type == "checkbox" && userfield.input_required == 1)
|
||||
{
|
||||
input.prop("indeterminate", true);
|
||||
input.on("change", function()
|
||||
input.on("change", function ()
|
||||
{
|
||||
input.removeAttr("required");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("form").each(function()
|
||||
$("form").each(function ()
|
||||
{
|
||||
Grocy.FrontendHelpers.ValidateForm(this.id);
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
function (xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
@@ -214,9 +214,9 @@ Grocy.Components.UserfieldsForm.Load = function()
|
||||
// Load object field values
|
||||
|
||||
Grocy.Api.Get('userfields/' + $("#userfields-form").data("entity") + '/' + Grocy.EditObjectId,
|
||||
function(result)
|
||||
function (result)
|
||||
{
|
||||
$.each(result, function(key, value)
|
||||
$.each(result, function (key, value)
|
||||
{
|
||||
var input = $(".userfield-input[data-userfield-name='" + key + "']");
|
||||
|
||||
@@ -248,12 +248,12 @@ Grocy.Components.UserfieldsForm.Load = function()
|
||||
var formGroup = input.parent().parent().parent();
|
||||
|
||||
formGroup.find("label.custom-file-label").text(fileName);
|
||||
formGroup.find(".userfield-file-show").attr('href', U('/files/userfiles/' + value));
|
||||
formGroup.find(".userfield-file-show").attr('href', U('/api/files/userfiles/' + value));
|
||||
formGroup.find('.userfield-file-show').removeClass('d-none');
|
||||
formGroup.find('img.userfield-current-file').attr('src', U('/files/userfiles/' + value + '?force_serve_as=picture&best_fit_width=250&best_fit_height=250'));
|
||||
formGroup.find('img.userfield-current-file').attr('src', U('/api/files/userfiles/' + value + '?force_serve_as=picture&best_fit_width=250&best_fit_height=250'));
|
||||
|
||||
formGroup.find('.userfield-file-delete').click(
|
||||
function()
|
||||
function ()
|
||||
{
|
||||
formGroup.find("label.custom-file-label").text(__t("No file selected"));
|
||||
formGroup.find(".userfield-file-show").addClass('d-none');
|
||||
@@ -262,7 +262,7 @@ Grocy.Components.UserfieldsForm.Load = function()
|
||||
}
|
||||
);
|
||||
|
||||
input.on("change", function(e)
|
||||
input.on("change", function (e)
|
||||
{
|
||||
formGroup.find(".userfield-file-show").addClass('d-none');
|
||||
});
|
||||
@@ -287,12 +287,12 @@ Grocy.Components.UserfieldsForm.Load = function()
|
||||
}
|
||||
});
|
||||
|
||||
$("form").each(function()
|
||||
$("form").each(function ()
|
||||
{
|
||||
Grocy.FrontendHelpers.ValidateForm(this.id);
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
function (xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
@@ -300,7 +300,7 @@ Grocy.Components.UserfieldsForm.Load = function()
|
||||
}
|
||||
}
|
||||
|
||||
Grocy.Components.UserfieldsForm.Clear = function()
|
||||
Grocy.Components.UserfieldsForm.Clear = function ()
|
||||
{
|
||||
if (!$("#userfields-form").length)
|
||||
{
|
||||
@@ -308,9 +308,9 @@ Grocy.Components.UserfieldsForm.Clear = function()
|
||||
}
|
||||
|
||||
Grocy.Api.Get('objects/userfields?query[]=entity=' + $("#userfields-form").data("entity"),
|
||||
function(result)
|
||||
function (result)
|
||||
{
|
||||
$.each(result, function(key, userfield)
|
||||
$.each(result, function (key, userfield)
|
||||
{
|
||||
var input = $(".userfield-input[data-userfield-name='" + userfield.name + "']");
|
||||
|
||||
@@ -328,13 +328,13 @@ Grocy.Components.UserfieldsForm.Clear = function()
|
||||
var formGroup = input.parent().parent().parent();
|
||||
|
||||
formGroup.find("label.custom-file-label").text("");
|
||||
formGroup.find(".userfield-file-show").attr('href', U('/files/userfiles/' + value));
|
||||
formGroup.find(".userfield-file-show").attr('href', U('/api/files/userfiles/' + value));
|
||||
formGroup.find('.userfield-file-show').removeClass('d-none');
|
||||
formGroup.find('img.userfield-current-file')
|
||||
.attr('src', U('/files/userfiles/' + value + '?force_serve_as=picture&best_fit_width=250&best_fit_height=250'));
|
||||
.attr('src', U('/api/files/userfiles/' + value + '?force_serve_as=picture&best_fit_width=250&best_fit_height=250'));
|
||||
|
||||
formGroup.find('.userfield-file-delete').click(
|
||||
function()
|
||||
function ()
|
||||
{
|
||||
formGroup.find("label.custom-file-label").text(__t("No file selected"));
|
||||
formGroup.find(".userfield-file-show").addClass('d-none');
|
||||
@@ -342,7 +342,7 @@ Grocy.Components.UserfieldsForm.Clear = function()
|
||||
}
|
||||
);
|
||||
|
||||
input.on("change", function(e)
|
||||
input.on("change", function (e)
|
||||
{
|
||||
formGroup.find(".userfield-file-show").addClass('d-none');
|
||||
});
|
||||
@@ -361,19 +361,19 @@ Grocy.Components.UserfieldsForm.Clear = function()
|
||||
}
|
||||
});
|
||||
|
||||
$("form").each(function()
|
||||
$("form").each(function ()
|
||||
{
|
||||
Grocy.FrontendHelpers.ValidateForm(this.id);
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
function (xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$(".userfield-link").keyup(function(e)
|
||||
$(".userfield-link").keyup(function (e)
|
||||
{
|
||||
var formRow = $(this).parent().parent();
|
||||
var title = formRow.find(".userfield-link-title").val();
|
||||
@@ -387,15 +387,15 @@ $(".userfield-link").keyup(function(e)
|
||||
formRow.find(".userfield-input").val(JSON.stringify(value)).addClass("is-dirty");
|
||||
});
|
||||
|
||||
$(".userfield-input").change(function(e)
|
||||
$(".userfield-input").change(function (e)
|
||||
{
|
||||
$("form").each(function()
|
||||
$("form").each(function ()
|
||||
{
|
||||
Grocy.FrontendHelpers.ValidateForm(this.id);
|
||||
});
|
||||
});
|
||||
|
||||
$(".userfield-input.selectpicker").on("changed.bs.select", function()
|
||||
$(".userfield-input.selectpicker").on("changed.bs.select", function ()
|
||||
{
|
||||
$(this).addClass("is-dirty");
|
||||
});
|
||||
|
||||
+16
-16
@@ -8,7 +8,7 @@
|
||||
style: 'single',
|
||||
selector: 'tr td:not(:first-child)'
|
||||
},
|
||||
'initComplete': function()
|
||||
'initComplete': function ()
|
||||
{
|
||||
this.api().row({ order: 'current' }, 0).select();
|
||||
DisplayEquipment($('#equipment-table tbody tr:eq(0)').data("equipment-id"));
|
||||
@@ -17,7 +17,7 @@
|
||||
$('#equipment-table tbody').removeClass("d-none");
|
||||
equipmentTable.columns.adjust().draw();
|
||||
|
||||
equipmentTable.on('select', function(e, dt, type, indexes)
|
||||
equipmentTable.on('select', function (e, dt, type, indexes)
|
||||
{
|
||||
if (type === 'row')
|
||||
{
|
||||
@@ -29,7 +29,7 @@ equipmentTable.on('select', function(e, dt, type, indexes)
|
||||
function DisplayEquipment(id)
|
||||
{
|
||||
Grocy.Api.Get('objects/equipment/' + id,
|
||||
function(equipmentItem)
|
||||
function (equipmentItem)
|
||||
{
|
||||
$(".selected-equipment-name").text(equipmentItem.name);
|
||||
$("#description-tab-content").html(equipmentItem.description);
|
||||
@@ -59,14 +59,14 @@ function DisplayEquipment(id)
|
||||
if (equipmentItem.userfields != null)
|
||||
{
|
||||
Grocy.Api.Get('objects/userfields?query[]=entity=equipment&query[]=type=file',
|
||||
function(result)
|
||||
function (result)
|
||||
{
|
||||
$.each(result, function(key, userfield)
|
||||
$.each(result, function (key, userfield)
|
||||
{
|
||||
var userfieldFile = equipmentItem.userfields[userfield.name];
|
||||
if (userfieldFile)
|
||||
{
|
||||
var pdfUrl = U('/files/userfiles/' + userfieldFile);
|
||||
var pdfUrl = U('/api/files/userfiles/' + userfieldFile);
|
||||
$("#file-userfield-" + userfield.name + "-embed").attr("src", pdfUrl);
|
||||
$("#file-userfield-" + userfield.name + "-download-button").attr("href", pdfUrl);
|
||||
$("#file-userfield-" + userfield.name + "-embed").removeClass("d-none");
|
||||
@@ -82,21 +82,21 @@ function DisplayEquipment(id)
|
||||
}
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
function (xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
function(xhr)
|
||||
function (xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$("#search").on("keyup", Delay(function()
|
||||
$("#search").on("keyup", Delay(function ()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
@@ -107,13 +107,13 @@ $("#search").on("keyup", Delay(function()
|
||||
equipmentTable.search(value).draw();
|
||||
}, Grocy.FormFocusDelay));
|
||||
|
||||
$("#clear-filter-button").on("click", function()
|
||||
$("#clear-filter-button").on("click", function ()
|
||||
{
|
||||
$("#search").val("");
|
||||
equipmentTable.search("").draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.equipment-delete-button', function(e)
|
||||
$(document).on('click', '.equipment-delete-button', function (e)
|
||||
{
|
||||
var objectName = $(e.currentTarget).attr('data-equipment-name');
|
||||
var objectId = $(e.currentTarget).attr('data-equipment-id');
|
||||
@@ -131,16 +131,16 @@ $(document).on('click', '.equipment-delete-button', function(e)
|
||||
className: 'btn-danger'
|
||||
}
|
||||
},
|
||||
callback: function(result)
|
||||
callback: function (result)
|
||||
{
|
||||
if (result === true)
|
||||
{
|
||||
Grocy.Api.Delete('objects/equipment/' + objectId, {},
|
||||
function(result)
|
||||
function (result)
|
||||
{
|
||||
window.location.href = U('/equipment');
|
||||
},
|
||||
function(xhr)
|
||||
function (xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
@@ -150,7 +150,7 @@ $(document).on('click', '.equipment-delete-button', function(e)
|
||||
});
|
||||
});
|
||||
|
||||
$(".selectedEquipmentInstructionManualToggleFullscreenButton").on('click', function(e)
|
||||
$(".selectedEquipmentInstructionManualToggleFullscreenButton").on('click', function (e)
|
||||
{
|
||||
var button = $(e.currentTarget);
|
||||
var card = button.closest(".selectedEquipmentInstructionManualCard");
|
||||
@@ -163,7 +163,7 @@ $(".selectedEquipmentInstructionManualToggleFullscreenButton").on('click', funct
|
||||
ResizeResponsiveEmbeds();
|
||||
});
|
||||
|
||||
$("#selectedEquipmentDescriptionToggleFullscreenButton").on('click', function(e)
|
||||
$("#selectedEquipmentDescriptionToggleFullscreenButton").on('click', function (e)
|
||||
{
|
||||
$("#selectedEquipmentDescriptionCard").toggleClass("fullscreen");
|
||||
$("#selectedEquipmentDescriptionCard .card-header").toggleClass("fixed-top");
|
||||
|
||||
@@ -57,8 +57,6 @@ $app->group('', function (RouteCollectorProxy $group)
|
||||
$group->get('/user/{userId}/permissions', [UsersController::class, 'PermissionList']);
|
||||
$group->get('/usersettings', [UsersController::class, 'UserSettings']);
|
||||
|
||||
$group->get('/files/{group}/{fileName}', [FilesApiController::class, 'ShowFile']);
|
||||
|
||||
// Stock master data routes
|
||||
$group->get('/products', [StockController::class, 'ProductsList']);
|
||||
$group->get('/product/{productId}', [StockController::class, 'ProductEditForm']);
|
||||
|
||||
@@ -38,12 +38,12 @@ $excludeFieldTypes = [];
|
||||
<a href="{{ $link }}"
|
||||
target="_blank">{{ $title }}</a>
|
||||
@elseif($userfield->type == \Grocy\Services\UserfieldsService::USERFIELD_TYPE_FILE && !empty($userfieldObject->value))
|
||||
<a href="{{ $U('/files/userfiles/'. $userfieldObject->value) }}"
|
||||
<a href="{{ $U('/api/files/userfiles/'. $userfieldObject->value) }}"
|
||||
target="_blank">{{ base64_decode(explode('_', $userfieldObject->value)[1]) }}</a>
|
||||
@elseif($userfield->type == \Grocy\Services\UserfieldsService::USERFIELD_TYPE_IMAGE && !empty($userfieldObject->value))
|
||||
<a class="show-as-dialog-link"
|
||||
href="{{ $U('/files/userfiles/'. $userfieldObject->value . '?force_serve_as=picture') }}">
|
||||
<img src="{{ $U('/files/userfiles/'. $userfieldObject->value . '?force_serve_as=picture&best_fit_width=32&best_fit_height=32') }}"
|
||||
href="{{ $U('/api/files/userfiles/'. $userfieldObject->value . '?force_serve_as=picture') }}">
|
||||
<img src="{{ $U('/api/files/userfiles/'. $userfieldObject->value . '?force_serve_as=picture&best_fit_width=32&best_fit_height=32') }}"
|
||||
title="{{ base64_decode(explode('_', $userfieldObject->value)[1]) }}"
|
||||
alt="{{ base64_decode(explode('_', $userfieldObject->value)[1]) }}"
|
||||
loading="lazy">
|
||||
|
||||
@@ -476,7 +476,7 @@
|
||||
<i class="fa-solid fa-user"></i>
|
||||
@else
|
||||
<img class="rounded-circle"
|
||||
src="{{ $U('/files/userpictures/' . base64_encode(GROCY_USER_PICTURE_FILE_NAME) . '_' . base64_encode(GROCY_USER_PICTURE_FILE_NAME) . '?force_serve_as=picture&best_fit_width=32&best_fit_height=32') }}"
|
||||
src="{{ $U('/api/files/userpictures/' . base64_encode(GROCY_USER_PICTURE_FILE_NAME) . '?force_serve_as=picture&best_fit_width=32&best_fit_height=32') }}"
|
||||
loading="lazy">
|
||||
@endif
|
||||
{{ GROCY_USER_USERNAME }}
|
||||
|
||||
Reference in New Issue
Block a user