mirror of
https://github.com/snipe/snipe-it.git
synced 2024-12-25 21:54:14 -08:00
Add image upload to user edit [ch10508] (#7877)
* Use correct Request include * Updated to use additional form request * Added SVG sanitizer * Added response method to form request * Allow ImageUploadRequest to accept fieldname params, added SVG sanitization, fixed delete * Fixed upload path for avatars * Added fieldname variable to blade partial for image upload * Added enctype="multipart/form-data" to form to allow uploads * Added image field * Updated Request::old() to use $request->old() * Fixed derp in edit blade referring to $item when it should be $user * Added svg+xml to image rule
This commit is contained in:
parent
9aed12c5aa
commit
039f5da0e1
|
@ -5,6 +5,7 @@ use App\Helpers\Helper;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Controllers\UserNotFoundException;
|
use App\Http\Controllers\UserNotFoundException;
|
||||||
use App\Http\Requests\SaveUserRequest;
|
use App\Http\Requests\SaveUserRequest;
|
||||||
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\Group;
|
use App\Models\Group;
|
||||||
|
@ -19,7 +20,7 @@ use Redirect;
|
||||||
use Str;
|
use Str;
|
||||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||||
use View;
|
use View;
|
||||||
use Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,12 +66,12 @@ class UsersController extends Controller
|
||||||
|
|
||||||
$userGroups = collect();
|
$userGroups = collect();
|
||||||
|
|
||||||
if (Request::old('groups')) {
|
if ($request->old('groups')) {
|
||||||
$userGroups = Group::whereIn('id', Request::old('groups'))->pluck('name', 'id');
|
$userGroups = Group::whereIn('id', $request->old('groups'))->pluck('name', 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
$permissions = config('permissions');
|
$permissions = config('permissions');
|
||||||
$userPermissions = Helper::selectedPermissionsArray($permissions, Request::old('permissions', array()));
|
$userPermissions = Helper::selectedPermissionsArray($permissions, $request->old('permissions', array()));
|
||||||
$permissions = $this->filterDisplayable($permissions);
|
$permissions = $this->filterDisplayable($permissions);
|
||||||
|
|
||||||
$user = new User;
|
$user = new User;
|
||||||
|
@ -125,6 +126,8 @@ class UsersController extends Controller
|
||||||
}
|
}
|
||||||
$user->permissions = json_encode($permissions_array);
|
$user->permissions = json_encode($permissions_array);
|
||||||
|
|
||||||
|
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, '', 'avatar', 'avatars');
|
||||||
|
|
||||||
if ($user->save()) {
|
if ($user->save()) {
|
||||||
if ($request->filled('groups')) {
|
if ($request->filled('groups')) {
|
||||||
$user->groups()->sync($request->input('groups'));
|
$user->groups()->sync($request->input('groups'));
|
||||||
|
@ -201,7 +204,7 @@ class UsersController extends Controller
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function update(SaveUserRequest $request, $id = null)
|
public function update(Request $request, $id = null)
|
||||||
{
|
{
|
||||||
// We need to reverse the UI specific logic for our
|
// We need to reverse the UI specific logic for our
|
||||||
// permissions here before we update the user.
|
// permissions here before we update the user.
|
||||||
|
@ -218,6 +221,7 @@ class UsersController extends Controller
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$user = User::findOrFail($id);
|
$user = User::findOrFail($id);
|
||||||
|
app('App\Http\Requests\SaveUserRequest');
|
||||||
|
|
||||||
if ($user->id == $request->input('manager_id')) {
|
if ($user->id == $request->input('manager_id')) {
|
||||||
return redirect()->back()->withInput()->with('error', 'You cannot be your own manager.');
|
return redirect()->back()->withInput()->with('error', 'You cannot be your own manager.');
|
||||||
|
@ -291,6 +295,9 @@ class UsersController extends Controller
|
||||||
|
|
||||||
$user->permissions = json_encode($permissions_array);
|
$user->permissions = json_encode($permissions_array);
|
||||||
|
|
||||||
|
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, '', 'avatar', 'avatars');
|
||||||
|
|
||||||
|
|
||||||
// Was the user updated?
|
// Was the user updated?
|
||||||
if ($user->save()) {
|
if ($user->save()) {
|
||||||
// Redirect to the user page
|
// Redirect to the user page
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Http\Requests;
|
||||||
|
|
||||||
use App\Models\SnipeModel;
|
use App\Models\SnipeModel;
|
||||||
use Intervention\Image\Facades\Image;
|
use Intervention\Image\Facades\Image;
|
||||||
|
use enshrined\svgSanitize\Sanitizer;
|
||||||
use Storage;
|
use Storage;
|
||||||
|
|
||||||
class ImageUploadRequest extends Request
|
class ImageUploadRequest extends Request
|
||||||
|
@ -26,8 +27,8 @@ class ImageUploadRequest extends Request
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'image' => 'mimes:png,gif,jpg,jpeg,svg',
|
'image' => 'mimes:png,gif,jpg,jpeg,svg,bmp,svg+xml',
|
||||||
'avatar' => 'mimes:png,gif,jpg,jpeg,svg',
|
'avatar' => 'mimes:png,gif,jpg,jpeg,svg,bmp,svg+xml',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,46 +43,65 @@ 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 = 550, $path = null)
|
public function handleImages($item, $w = 550, $fieldname = 'image', $path = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
$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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
\Log::debug('Image path is: '.$path);
|
||||||
|
\Log::debug('Image fieldname is: '.$fieldname);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ($this->hasFile($fieldname)) {
|
||||||
|
|
||||||
if ($this->hasFile('image')) {
|
|
||||||
if (!config('app.lock_passwords')) {
|
if (!config('app.lock_passwords')) {
|
||||||
|
|
||||||
if(!Storage::disk('public')->exists($path)) Storage::disk('public')->makeDirectory($path, 775);
|
if (!Storage::disk('public')->exists($path)) Storage::disk('public')->makeDirectory($path, 775);
|
||||||
|
|
||||||
$upload = $image = $this->file('image');
|
$image = $this->file($fieldname);
|
||||||
$ext = $image->getClientOriginalExtension();
|
$ext = $image->getClientOriginalExtension();
|
||||||
$file_name = $type.'-'.str_random(18).'.'.$ext;
|
$file_name = $type.'-'.str_random(18).'.'.$ext;
|
||||||
|
|
||||||
if ($image->getClientOriginalExtension()!='svg') {
|
if ($image->getClientOriginalExtension()!='svg') {
|
||||||
|
|
||||||
$upload = Image::make($image->getRealPath())->resize(null, $w, function ($constraint) {
|
$upload = Image::make($image->getRealPath())->resize(null, $w, function ($constraint) {
|
||||||
$constraint->aspectRatio();
|
$constraint->aspectRatio();
|
||||||
$constraint->upsize();
|
$constraint->upsize();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// This requires a string instead of an object, so we use ($string)
|
||||||
|
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
|
||||||
|
} else {
|
||||||
|
$sanitizer = new Sanitizer();
|
||||||
|
$dirtySVG = file_get_contents($image->getRealPath());
|
||||||
|
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||||
|
Storage::disk('public')->put($path.'/'.$file_name, $cleanSVG);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This requires a string instead of an object, so we use ($string)
|
// Remove current image if it exists and we're uploading a new one
|
||||||
Storage::disk('public')->put($path.'/'.$file_name, (string)$upload->encode());
|
if (($item->{$fieldname}) && (Storage::disk('public')->exists($path.'/'.$item->{$fieldname}))) {
|
||||||
|
Storage::disk('public')->delete($path.'/'.$item->{$fieldname});
|
||||||
// Remove Current image if exists
|
} else {
|
||||||
if (($item->image) && (file_exists($path.'/'.$item->image))) {
|
\Log::debug('Could not delete old file. '.$path.'/'.$item->{$fieldname}.' does not exist?');
|
||||||
Storage::disk('public')->delete($path.'/'.$file_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$item->image = $file_name;
|
// Assign the new filename as the fieldname
|
||||||
|
$item->{$fieldname} = $file_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the user isn't uploading anything new but wants to delete their old image, do so
|
||||||
} elseif ($this->input('image_delete')=='1') {
|
} elseif ($this->input('image_delete')=='1') {
|
||||||
Storage::disk('public')->delete($path.'/'.$item->image);
|
Storage::disk('public')->delete($path.'/'.$item->{$fieldname});
|
||||||
$item->image = null;
|
$item->{$fieldname} = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $item;
|
return $item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,12 @@ class SaveUserRequest extends FormRequest
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function response(array $errors)
|
||||||
|
{
|
||||||
|
return $this->redirector->back()->withInput()->withErrors($errors, $this->errorBag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the validation rules that apply to the request.
|
* Get the validation rules that apply to the request.
|
||||||
*
|
*
|
||||||
|
|
|
@ -76,7 +76,7 @@ class SettingsServiceProvider extends ServiceProvider
|
||||||
|
|
||||||
// Users
|
// Users
|
||||||
\App::singleton('users_upload_path', function(){
|
\App::singleton('users_upload_path', function(){
|
||||||
return 'users/';
|
return 'avatars/';
|
||||||
});
|
});
|
||||||
|
|
||||||
\App::singleton('users_upload_url', function(){
|
\App::singleton('users_upload_url', function(){
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<div class="form-group {{ $errors->has('image') ? 'has-error' : '' }}">
|
<div class="form-group {{ $errors->has((isset($fieldname) ? $fieldname : 'image')) ? 'has-error' : '' }}">
|
||||||
<label class="col-md-3 control-label" for="image">{{ trans('general.image_upload') }}</label>
|
<label class="col-md-3 control-label" for="image">{{ trans('general.image_upload') }}</label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<label class="btn btn-default">
|
<label class="btn btn-default">
|
||||||
{{ 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%">
|
<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,image/svg+xml,image/bmp" style="display:none; max-width: 90%">
|
||||||
</label>
|
</label>
|
||||||
<span class='label label-default' id="uploadFile-info"></span>
|
<span class='label label-default' id="uploadFile-info"></span>
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8 col-md-offset-2">
|
<div class="col-md-8 col-md-offset-2">
|
||||||
<form class="form-horizontal" method="post" autocomplete="off" action="{{ (isset($user->id)) ? route('users.update', ['user' => $user->id]) : route('users.store') }}" id="userForm">
|
<form class="form-horizontal" method="post" autocomplete="off" action="{{ (isset($user->id)) ? route('users.update', ['user' => $user->id]) : route('users.store') }}" enctype="multipart/form-data" id="userForm">
|
||||||
{{csrf_field()}}
|
{{csrf_field()}}
|
||||||
|
|
||||||
@if($user->id)
|
@if($user->id)
|
||||||
|
@ -213,6 +213,22 @@
|
||||||
@include ('partials.forms.edit.company-select', ['translated_name' => trans('general.select_company'), 'fieldname' => 'company_id'])
|
@include ('partials.forms.edit.company-select', ['translated_name' => trans('general.select_company'), 'fieldname' => 'company_id'])
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Image -->
|
||||||
|
@if ($user->avatar)
|
||||||
|
<div class="form-group {{ $errors->has('image_delete') ? 'has-error' : '' }}">
|
||||||
|
<label class="col-md-3 control-label" for="image_delete">{{ trans('general.image_delete') }}</label>
|
||||||
|
<div class="col-md-5">
|
||||||
|
{{ Form::checkbox('image_delete') }}
|
||||||
|
<img src="{{ Storage::disk('public')->url(app('users_upload_path').e($user->avatar)) }}" class="img-responsive" />
|
||||||
|
{!! $errors->first('image_delete', '<span class="alert-msg"><br>:message</span>') !!}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@include ('partials.forms.edit.image-upload', ['fieldname' => 'avatar'])
|
||||||
|
|
||||||
|
|
||||||
<!-- language -->
|
<!-- language -->
|
||||||
<div class="form-group {{ $errors->has('locale') ? 'has-error' : '' }}">
|
<div class="form-group {{ $errors->has('locale') ? 'has-error' : '' }}">
|
||||||
<label class="col-md-3 control-label" for="locale">{{ trans('general.language') }}</label>
|
<label class="col-md-3 control-label" for="locale">{{ trans('general.language') }}</label>
|
||||||
|
|
Loading…
Reference in a new issue