Merge pull request #8374 from snipe/fixes/moar_flysystem

WIP - More Flysystem fixes
This commit is contained in:
snipe 2020-08-31 09:45:27 -07:00 committed by GitHub
commit 8ec99ff433
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 92 additions and 135 deletions

View file

@ -20,7 +20,7 @@ class MoveUploadsToNewDisk extends Command
* *
* @var string * @var string
*/ */
protected $description = 'This will move your uploaded files to whatever your current disk is.'; protected $description = 'This will move your locally uploaded files to whatever your current disk is.';
/** /**
* Create a new command instance. * Create a new command instance.
@ -42,7 +42,7 @@ class MoveUploadsToNewDisk extends Command
if (config('filesystems.default')=='local') { if (config('filesystems.default')=='local') {
$this->error('Your current disk is set to local so we cannot proceed.'); $this->error('Your current disk is set to local so we cannot proceed.');
$this->warn("Please configure your .env settings for S3. \nChange your PUBLIC_FILESYSTEM_DISK value to 's3_public' and your PRIVATE_FILESYSTEM_DISK to s3_public."); $this->warn("Please configure your .env settings for S3. \nChange your PUBLIC_FILESYSTEM_DISK value to 's3_public' and your PRIVATE_FILESYSTEM_DISK to s3_private.");
return false; return false;
} }
$delete_local = $this->argument('delete_local'); $delete_local = $this->argument('delete_local');
@ -84,9 +84,9 @@ class MoveUploadsToNewDisk extends Command
} }
$logos = glob('public/uploads'."/logo*.*"); $logos = glob('public/uploads'."/setting*.*");
$this->info("\nThere are ".count($logos).' files that might be logos.'); $this->info("\nThere are ".count($logos).' files that might be logos.');
$type_count=0; $type_count = 0;
for ($l = 0; $l < count($logos); $l++) { for ($l = 0; $l < count($logos); $l++) {
$type_count++; $type_count++;
@ -102,6 +102,7 @@ class MoveUploadsToNewDisk extends Command
$private_uploads['imports'] = glob('storage/private_uploads/imports'."/*.*"); $private_uploads['imports'] = glob('storage/private_uploads/imports'."/*.*");
$private_uploads['licenses'] = glob('storage/private_uploads/licenses'."/*.*"); $private_uploads['licenses'] = glob('storage/private_uploads/licenses'."/*.*");
$private_uploads['users'] = glob('storage/private_uploads/users'."/*.*"); $private_uploads['users'] = glob('storage/private_uploads/users'."/*.*");
$private_uploads['backups'] = glob('storage/private_uploads/users'."/*.*");
foreach($private_uploads as $private_type => $private_upload) foreach($private_uploads as $private_type => $private_upload)

View file

@ -85,7 +85,7 @@ class AssetModelsController extends Controller
$model->fieldset_id = e($request->input('custom_fieldset')); $model->fieldset_id = e($request->input('custom_fieldset'));
} }
$model = $request->handleImages($model,600,null,null, public_path().'/uploads/models'); $model = $request->handleImages($model);
// Was it created? // Was it created?
if ($model->save()) { if ($model->save()) {

View file

@ -409,94 +409,43 @@ class SettingsController extends Controller
$setting->custom_css = $request->input('custom_css'); $setting->custom_css = $request->input('custom_css');
} }
$setting = $request->handleImages($setting,600,'logo','', 'logo');
if ($request->hasFile('logo')) {
$image = $request->file('logo');
$ext = $image->getClientOriginalExtension();
$setting->logo = $file_name = 'logo-'.date('U').'.'. $ext;
if ('svg' != $image->getClientOriginalExtension()) { if ('1' == $request->input('clear_logo')) {
$upload = Image::make($image->getRealPath())->resize(null, 150, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
}
// This requires a string instead of an object, so we use ($string)
Storage::disk('public')->put($file_name, (string) $upload->encode());
// Remove Current image if exists
if (($setting->logo) && (file_exists($file_name))) {
Storage::disk('public')->delete($file_name);
}
} elseif ('1' == $request->input('clear_logo')) {
Storage::disk('public')->delete($setting->logo); Storage::disk('public')->delete($setting->logo);
$setting->logo = null; $setting->logo = null;
$setting->brand = 1; $setting->brand = 1;
} }
if ($request->hasFile('email_logo')) { $setting = $request->handleImages($setting,600,'email_logo','', 'email_logo');
$email_image = $email_upload = $request->file('email_logo');
$email_ext = $email_image->getClientOriginalExtension();
$setting->email_logo = $email_file_name = 'email_logo.' . $email_ext;
if ('svg' != $email_image->getClientOriginalExtension()) {
$email_upload = Image::make($email_image->getRealPath())->resize(null, 100, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
}
// This requires a string instead of an object, so we use ($string) if ('1' == $request->input('clear_email_logo')) {
Storage::disk('public')->put($email_file_name, (string) $email_upload->encode());
// Remove Current image if exists
if (($setting->email_logo) && (file_exists($email_file_name))) {
Storage::disk('public')->delete($email_file_name);
}
} elseif ('1' == $request->input('clear_email_logo')) {
Storage::disk('public')->delete($setting->email_logo); Storage::disk('public')->delete($setting->email_logo);
$setting->email_logo = null; $setting->email_logo = null;
// If they are uploading an image, validate it and upload it // If they are uploading an image, validate it and upload it
} }
// If the user wants to clear the label logo... $setting = $request->handleImages($setting,600,'label_logo','', 'label_logo');
if ($request->hasFile('label_logo')) {
$image = $request->file('label_logo');
$ext = $image->getClientOriginalExtension();
$setting->label_logo = $label_file_name = 'label_logo.' . $ext;
if ('svg' != $image->getClientOriginalExtension()) {
$upload = Image::make($image->getRealPath())->resize(null, 100, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
}
// This requires a string instead of an object, so we use ($string) if ('1' == $request->input('clear_label_logo')) {
Storage::disk('public')->put($label_file_name, (string) $upload->encode());
// Remove Current image if exists
if (($setting->label_logo) && (file_exists($label_file_name))) {
Storage::disk('public')->delete($label_file_name);
}
} elseif ('1' == $request->input('clear_label_logo')) {
Storage::disk('public')->delete($setting->label_logo); Storage::disk('public')->delete($setting->label_logo);
$setting->label_logo = null; $setting->label_logo = null;
// If they are uploading an image, validate it and upload it
} }
// If the user wants to clear the favicon... // If the user wants to clear the favicon...
if ($request->hasFile('favicon')) { if ($request->hasFile('favicon')) {
$favicon_image = $favicon_upload = $request->file('favicon'); $favicon_image = $favicon_upload = $request->file('favicon');
$favicon_ext = $favicon_image->getClientOriginalExtension(); $favicon_ext = $favicon_image->getClientOriginalExtension();
$setting->favicon = $favicon_file_name = 'favicon-uploaded.' . $favicon_ext; $setting->favicon = $favicon_file_name = 'favicon-uploaded.' . $favicon_ext;
if (('ico' != $favicon_image->getClientOriginalExtension()) && ('svg' != $favicon_image->getClientOriginalExtension())) { if (($favicon_image->getClientOriginalExtension()!='ico') && ($favicon_image->getClientOriginalExtension()!='svg')) {
$favicon_upload = Image::make($favicon_image->getRealPath())->resize(null, 36, function ($constraint) { $favicon_upload = Image::make($favicon_image->getRealPath())->resize(null, 36, function ($constraint) {
$constraint->aspectRatio(); $constraint->aspectRatio();
$constraint->upsize(); $constraint->upsize();
@ -509,11 +458,6 @@ class SettingsController extends Controller
} }
// Remove Current image if exists // Remove Current image if exists
if (($setting->favicon) && (file_exists($favicon_file_name))) { if (($setting->favicon) && (file_exists($favicon_file_name))) {
Storage::disk('public')->delete($favicon_file_name); Storage::disk('public')->delete($favicon_file_name);
@ -1064,19 +1008,26 @@ class SettingsController extends Controller
*/ */
public function getBackups() public function getBackups()
{ {
$path = storage_path() . '/app/' . config('backup.backup.name');
$path = 'backups'; $path = 'app/backups';
$backup_files = Storage::files($path); $backup_files = Storage::files($path);
$files = []; $files = [];
if (count($backup_files) > 0) { if (count($backup_files) > 0) {
for ($f = 0; $f < count($backup_files); ++$f) { for ($f = 0; $f < count($backup_files); ++$f) {
$files[] = [
'filename' => basename($backup_files[$f]), // Skip dotfiles like .gitignore and .DS_STORE
'filesize' => Setting::fileSizeConvert(Storage::size($backup_files[$f])), if ((substr(basename($backup_files[$f]), 0, 1) != '.')) {
'modified' => Storage::lastModified($backup_files[$f]),
]; $files[] = [
'filename' => basename($backup_files[$f]),
'filesize' => Setting::fileSizeConvert(Storage::size($backup_files[$f])),
'modified' => Storage::lastModified($backup_files[$f]),
];
}
} }
} }
@ -1124,13 +1075,15 @@ class SettingsController extends Controller
* *
* @since [v1.8] * @since [v1.8]
* *
* @return Redirect * @return Storage
*/ */
public function downloadFile($filename = null) public function downloadFile($filename = null)
{ {
$path = 'app/backups';
if (! config('app.lock_passwords')) { if (! config('app.lock_passwords')) {
if (Storage::exists($filename)) { if (Storage::exists($path . '/' . $filename)) {
return Response::download(Storage::url('') . e($filename)); return Storage::download($path . '/' . $filename);
} else { } else {
// Redirect to the backup page // Redirect to the backup page
return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found')); return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found'));
@ -1153,12 +1106,11 @@ class SettingsController extends Controller
public function deleteFile($filename = null) public function deleteFile($filename = null)
{ {
if (! config('app.lock_passwords')) { if (! config('app.lock_passwords')) {
$path = 'backups'; $path = 'app/backups';
if (Storage::exists($path . '/' . $filename)) { if (Storage::exists($path . '/' . $filename)) {
try { try {
Storage::delete($path . '/' . $filename); Storage::delete($path . '/' . $filename);
return redirect()->route('settings.backups.index')->with('success', trans('admin/settings/message.backup.file_deleted')); return redirect()->route('settings.backups.index')->with('success', trans('admin/settings/message.backup.file_deleted'));
} catch (\Exception $e) { } catch (\Exception $e) {
\Log::debug($e); \Log::debug($e);

View file

@ -291,9 +291,11 @@ class UsersController extends Controller
$user->permissions = json_encode($permissions_array); $user->permissions = json_encode($permissions_array);
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar'); // Handle uploaded avatar
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
//\Log::debug(print_r($user, true));
// Was the user updated? // Was the user updated?
if ($user->save()) { if ($user->save()) {

View file

@ -43,53 +43,53 @@ class ImageUploadRequest extends Request
* @param String $path location for uploaded images, defaults to uploads/plural of item type. * @param String $path location for uploaded images, defaults to uploads/plural of item type.
* @return SnipeModel Target asset is being checked out to. * @return SnipeModel Target asset is being checked out to.
*/ */
public function handleImages($item, $w = 600, $fieldname = 'image', $path = null, $db_fieldname = 'image') public function handleImages($item, $w = 600, $form_fieldname = null, $path = null, $db_fieldname = 'image')
{ {
\Log::debug('Handle file upload');
$type = strtolower(class_basename(get_class($item))); $type = strtolower(class_basename(get_class($item)));
if (is_null($path)) { if (is_null($path)) {
$path = str_plural($type); $path = str_plural($type);
if ($type=='assetmodel') { if ($type == 'assetmodel') {
\Log::debug('This is an asset model! Override the path');
$path = 'models'; $path = 'models';
} }
if ($type=='user') { if ($type == 'user') {
\Log::debug('This is a user! Override the path');
$path = 'avatars'; $path = 'avatars';
} }
} }
\Log::info('Path is: '.$path); if (is_null($form_fieldname)) {
$form_fieldname = 'image';
}
// This is dumb, but we need it for overriding field names for exceptions like avatars and logo uploads
if (is_null($db_fieldname)) {
$use_db_field = $form_fieldname;
} else {
$use_db_field = $db_fieldname;
}
\Log::info('Image path is: '.$path);
\Log::debug('Type is: '.$type); \Log::debug('Type is: '.$type);
\Log::debug('Image path is: '.$path); \Log::debug('Form fieldname is: '.$form_fieldname);
\Log::debug('Image fieldname is: '.$fieldname); \Log::debug('DB fieldname is: '.$use_db_field);
\Log::debug('Trying to upload to '. $path); \Log::debug('Trying to upload to '. $path);
if ($this->hasFile($fieldname)) { \Log::debug($this->file());
if ($this->hasFile($form_fieldname)) {
if (!config('app.lock_passwords')) { if (!config('app.lock_passwords')) {
if (!Storage::disk('public')->exists($path)) $image = $this->file($form_fieldname);
{
\Log::debug($path);
// Storage::disk('public')->makeDirectory($path, 775);
}
if (!is_dir($path)) {
\Log::info($path.' does not exist');
//mkdir($path);
}
$image = $this->file($fieldname);
$ext = $image->getClientOriginalExtension(); $ext = $image->getClientOriginalExtension();
$file_name = $type.'-'.str_random(18).'.'.$ext; $file_name = $type.'-'.$form_fieldname.'-'.str_random(10).'.'.$ext;
\Log::info('File name will be: '.$file_name); \Log::info('File name will be: '.$file_name);
\Log::debug('File extension is: '. $ext);
if ($image->getClientOriginalExtension()!=='svg') { if ($image->getClientOriginalExtension()!=='svg') {
\Log::debug('Not an SVG - resize'); \Log::debug('Not an SVG - resize');
@ -102,6 +102,7 @@ class ImageUploadRequest extends Request
// This requires a string instead of an object, so we use ($string) // This requires a string instead of an object, so we use ($string)
Storage::disk('public')->put($path.'/'.$file_name, (string)$upload->encode()); Storage::disk('public')->put($path.'/'.$file_name, (string)$upload->encode());
// If the file is an SVG, we need to clean it and NOT encode it // If the file is an SVG, we need to clean it and NOT encode it
} else { } else {
\Log::debug('This is an SVG'); \Log::debug('This is an SVG');
@ -120,40 +121,32 @@ class ImageUploadRequest extends Request
// Remove Current image if exists // Remove Current image if exists
if (($item->{$fieldname}) && (Storage::disk('public')->exists($path.'/'.$item->{$fieldname}))) { if (Storage::disk('public')->exists($path.'/'.$item->{$use_db_field})) {
\Log::debug('A file already exists that we are replacing - we should delete the old one.');
// Assign the new filename as the fieldname \Log::debug('A file already exists that we are replacing - we should delete the old one.');
if (is_null($db_fieldname)) {
$item->{$fieldname} = $file_name;
} else {
$item->{$db_fieldname} = $file_name;
}
try { try {
Storage::disk('public')->delete($path.'/'.$item->{$fieldname}); Storage::disk('public')->delete($path.'/'.$item->{$use_db_field});
\Log::debug('Old file '.$path.'/'.$file_name.' has been deleted.');
} catch (\Exception $e) { } catch (\Exception $e) {
\Log::debug('Could not delete old file. '.$path.'/'.$item->{$fieldname}.' does not exist?'); \Log::debug('Could not delete old file. '.$path.'/'.$file_name.' does not exist?');
} }
} }
$item->{$use_db_field} = $file_name;
} }
// If the user isn't uploading anything new but wants to delete their old image, do so // If the user isn't uploading anything new but wants to delete their old image, do so
} else { } else {
\Log::debug('No file passed for '.$form_fieldname);
if ($this->input('image_delete')=='1') { if ($this->input('image_delete')=='1') {
\Log::debug('Deleting image');
try { try {
Storage::disk('public')->delete($path . '/' . $item->{$use_db_field});
if (is_null($db_fieldname)) { $item->{$use_db_field} = null;
$item->{$fieldname} = null;
Storage::disk('public')->delete($path . '/' . $item->{$fieldname});
} else {
$item->{$db_fieldname} = null;
Storage::disk('public')->delete($path . '/' . $item->{$fieldname});
}
} catch (\Exception $e) { } catch (\Exception $e) {
\Log::debug($e); \Log::debug($e);
@ -163,7 +156,6 @@ class ImageUploadRequest extends Request
} }
return $item; return $item;
} }
} }

View file

@ -6,6 +6,7 @@ use App\Helpers\Helper;
use App\Models\Setting; use App\Models\Setting;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Storage;
/** /**
* Class UserPresenter * Class UserPresenter
@ -320,8 +321,9 @@ class UserPresenter extends Presenter
public function gravatar() public function gravatar()
{ {
if ($this->avatar) { if ($this->avatar) {
return config('app.url').'/uploads/avatars/'.$this->avatar; return Storage::disk('public')->url('avatars/'.e($this->avatar));
} }
if (Setting::getSettings()->load_remote=='1') { if (Setting::getSettings()->load_remote=='1') {

View file

@ -12,7 +12,6 @@
// This is janky, but necessary to figure out whether to include the .env in the backup // This is janky, but necessary to figure out whether to include the .env in the backup
$included_dirs = [ $included_dirs = [
base_path('public/uploads'), base_path('public/uploads'),
base_path('config'),
base_path('storage/private_uploads'), base_path('storage/private_uploads'),
base_path('storage/oauth-private.key'), base_path('storage/oauth-private.key'),
base_path('storage/oauth-public.key'), base_path('storage/oauth-public.key'),
@ -78,7 +77,7 @@ return [
* For a complete list of available customization options, see https://github.com/spatie/db-dumper * For a complete list of available customization options, see https://github.com/spatie/db-dumper
*/ */
'databases' => [ 'databases' => [
'mysql', env('DB_CONNECTION', 'mysql'),
], ],
], ],
@ -106,7 +105,7 @@ return [
* The disk names on which the backups will be stored. * The disk names on which the backups will be stored.
*/ */
'disks' => [ 'disks' => [
'local', 'backup',
], ],
], ],
@ -167,7 +166,7 @@ return [
'monitorBackups' => [ 'monitorBackups' => [
[ [
'name' => config('app.name'), 'name' => config('app.name'),
'disks' => ['local'], 'disks' => [env('PRIVATE_FILESYSTEM_DISK', 'local')],
'newestBackupsShouldNotBeOlderThanDays' => 1, 'newestBackupsShouldNotBeOlderThanDays' => 1,
'storageUsedMayNotBeHigherThanMegabytes' => 5000, 'storageUsedMayNotBeHigherThanMegabytes' => 5000,
], ],
@ -214,7 +213,7 @@ return [
/* /*
* The number of months for which one monthly backup must be kept. * The number of months for which one monthly backup must be kept.
*/ */
'keepMonthlyBackupsForMonths' => 4, 'keepMonthlyBackupsForMonths' => 3,
/* /*
* The number of years for which one yearly backup must be kept. * The number of years for which one yearly backup must be kept.

View file

@ -92,6 +92,11 @@ $config = [
'url_type' => env('RACKSPACE_URL_TYPE'), 'url_type' => env('RACKSPACE_URL_TYPE'),
], ],
'backup' => [
'driver' => env('PRIVATE_FILESYSTEM_DISK', 'local'),
'root' => storage_path('app'),
],
], ],
]; ];

View file

@ -6,7 +6,7 @@
<label class="btn btn-default" aria-hidden="true"> <label class="btn btn-default" aria-hidden="true">
{{ trans('button.select_file') }} {{ trans('button.select_file') }}
<input type="file" name="image" class="js-uploadFile" id="uploadFile" data-maxsize="{{ \App\Helpers\Helper::file_upload_max_size() }}" accept="image/gif,image/jpeg,image/png,image/svg" style="display:none; max-width: 90%" aria-label="image" aria-hidden="true"> <input type="file" name="{{ (isset($fieldname) ? $fieldname : 'image') }}" class="js-uploadFile" id="uploadFile" data-maxsize="{{ \App\Helpers\Helper::file_upload_max_size() }}" accept="image/gif,image/jpeg,image/png,image/svg" style="display:none; max-width: 90%" aria-label="image" aria-hidden="true">
</label> </label>
<span class='label label-default' id="uploadFile-info"></span> <span class='label label-default' id="uploadFile-info"></span>

View file

@ -29,7 +29,11 @@
<tbody> <tbody>
@foreach ($files as $file) @foreach ($files as $file)
<tr> <tr>
<td><a href="{{ Storage::url('backups/'.e($file['filename'])) }}">{{ $file['filename'] }}</a></td> <td>
<a href="{{ route('settings.backups.download', [$file['filename']]) }}">
{{ $file['filename'] }}
</a>
</td>
<td>{{ date("M d, Y g:i A", $file['modified']) }} </td> <td>{{ date("M d, Y g:i A", $file['modified']) }} </td>
<td>{{ $file['filesize'] }}</td> <td>{{ $file['filesize'] }}</td>
<td> <td>