I'm trying to create an register form that includes an image upload. When I submit the form, it stores an "/private/var/tmp/" path for the image on database and the image is not stored anywhere in the public folder. I don't know what I might be doing wrong. Please help.
My config/filesystems:
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
My controller CreateNewUser:
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
protected function validator(array $input)
{
return Validator::make( $input, [
'firstname' => ['required', 'string', 'max:255'],
'lastname' => ['required', 'string', 'max:255'],
'email' => [
'required',
'string',
'email',
'max:255',
Rule::unique(User::class),
],
'mobile' => ['required', 'int'],
'country' => ['required', 'string', 'max:255'],
'password' => $this->passwordRules(),
'db_upload' => ['required', 'image'] //This the image I want to upload
]);
}
public function register(Request $request)
{
$this->validator($request->all())->validate();
$imageUrl = $this->storeImage($request);
$input = $request->all();
$input['db_upload'] = $imageUrl;
$user = $this->create($input);
$this->guard()->login($user);
return $this->registered($request, $user)
?: redirect($this->redirectPath());
}
protected function storeImage(Request $request) {
$path = $request->file('db_upload')->store('public/uploads');
return substr($path, strlen('public/'));
}
public function create(array $input)
{
$user = User::create([
'firstname' => $input['firstname'],
'lastname' => $input['lastname'],
'email' => $input['email'],
'mobile' => $input['mobile'],
'country' => $input['email'],
'password' => Hash::make($input['password']),
'db_upload' => $input['db_upload'],
]);
$user->notify(new WelcomeEmailNotification());
return $user;
}
}
Try changing your storeImage function as below
protected function storeImage(Request $request) {
return $request->file('db_upload')->store('uploads', 'public');
}
Also ensure that you have created the symlink to the public disk by running php artisan storage:link and that after running the command there is a symlink visible in the <app-root>/public folder
Change the line of code that saves the file from:
$path = $request->file('db_upload')->store('public/uploads');
to
$path = $request->file('db_upload')->store('uploads', 'public');
The first argument is the path and the second argument is the disk you want to save to.
You can use the storePublicly() function to store the file in the public folder:
$file = $request->file('db_upload');
$path = $file
->storePublicly('files', ['disk' => 'public']);
Related
I deployed a Laravel-Livewire on Digital Ocean and now I'm having a Mixed content problem when I try to upload a file.
Here is the error:
UploadManager.js:131 Mixed Content: The page at 'https://intake.freejiji.ca/clients/3/extensions' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://intake.freejiji.ca/livewire/upload-file?expires=1625251608&signature=9d98c598db4f6fccc01c009bcfc3051c6a97b56f4058f4d9489a8d30d6d497c2'. This request has been blocked; the content must be served over HTTPS.
The error happens when after I click "Select File" and chose the .csv file I want. Since I'mdoing this on a livewire component I'm not sure how to fix this so that the request goes over HTTPS instead of HTTP.
I was able to fix similar problems on the app by changing "asset()" with "secure_asset()"
and "route()" with "secure_url()" but in this case I'm not sure what to do.
Here is the whole "Import" component:
<?php
namespace App\Http\Livewire\Modals;
use Validator;
use Livewire\Component;
use App\Http\Traits\Csv;
use App\Models\AccountUser;
use Livewire\WithFileUploads;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\Auth;
class ImportExtensions extends Component
{
use WithFileUploads;
public $clientID;
public $showModal = false;
public $upload;
public $columns;
public $fieldColumnMap = [
'first_name' => '',
'last_name' => '',
'email' => '',
'password' => '',
'extension' => '',
'user_type' => '',
];
protected $rules = [
'fieldColumnMap.first_name' => 'required|max:255',
'fieldColumnMap.last_name' => 'required|max:255',
'fieldColumnMap.email' => 'required|max:255',
'fieldColumnMap.password' => 'required|max:255',
'fieldColumnMap.extension' => 'required|max:255',
'fieldColumnMap.user_type' => 'required|max:255',
];
protected $validationAttributes = [
'fieldColumnMap.first_name' => 'First Name',
'fieldColumnMap.last_name' => 'Last Name',
'fieldColumnMap.email' => 'Email',
'fieldColumnMap.password' => 'Password',
'fieldColumnMap.extension' => 'Extension',
'fieldColumnMap.user_type' => 'User Type',
];
public function updatingUpload($value)
{
Validator::make(
['upload' => $value],
['upload' => 'required|mimes:csv'],
)->validate();
}
public function updatedUpload()
{
$this->columns = Csv::from($this->upload)->columns();
$this->guessWhichColumnsMapToWhichFields();
}
public function import()
{
// Validate that you are importing any data
$this->validate();
$importCount = 0;
Csv::from($this->upload)
->eachRow( function ($row) use (&$importCount){
$eachRow = $this->extractFieldsFromRow($row);
// Validate each Row of the csv file
$validatedData = Validator::make([
'first_name' => $eachRow['first_name'],
'last_name' => $eachRow['last_name'],
'email' => $eachRow['email'],
'password' => $eachRow['password'],
'extension' => $eachRow['extension'],
'user_type' => $eachRow['user_type'],
],[
'first_name' => 'required',
'last_name' => 'required',
'password' => 'required|max:255',
'user_type' => 'required|in:user,admin',
'email' => 'required|email|unique:account_users',
'extension' => ['required', 'numeric', Rule::unique('account_users', 'extension')
->where(function($query)
{return $query->where("account_id", $this->clientID);
})],
],);
if($validatedData->fails()){
$this->notify(['error','Oops something went wrong!']);
}else{
AccountUser::create([
'user_id' => Auth::user()->id,
'account_id' => $this->clientID,
'first_name' => $eachRow['first_name'],
'last_name' => $eachRow['last_name'],
'email' => $eachRow['email'],
'password' => $eachRow['password'],
'extension' => $eachRow['extension'],
'user_type' => $eachRow['user_type'],
]);
$importCount++;
}
});
$this->reset();
$this->emit('refreshExtensions');
if($importCount!=0) $this->notify(['success','Successfully Imported '.$importCount.' Extensions']);
}
public function guessWhichColumnsMapToWhichFields()
{
$guesses = [
'first_name' => ['first_name', 'name'],
'last_name' => ['last_name'],
'email' => ['email'],
'password' => ['password', 'pass'],
'extension' => ['extension', 'ext'],
'user_type' => ['user_type', 'user', 'type'],
];
foreach ($this->columns as $column) {
$match = collect($guesses)->search(fn($options) => in_array(strtolower($column), $options));
if ($match) $this->fieldColumnMap[$match] = $column;
}
}
public function extractFieldsFromRow($row)
{
$attributes = collect($this->fieldColumnMap)
->filter()
->mapWithKeys(function($heading, $field) use ($row) {
return [$field => $row[$heading]];
})
->toArray();
return $attributes;
}
public function downloadTemplate()
{
$filename = 'extensions_template.xls';
$path = public_path('files/' . $filename);
return response()->download($path, $filename, [
'Content-Type' => 'application/vnd.ms-excel',
'Content-Disposition' => 'inline; filename="' . $filename . '"'
]);
}
}
If you get mixed content problem it is mostly about you fetching the assets or resources from different http scheme. Here you are using HTTP to fetch data in HTTPS site. Change all the links to have HTTPS link.
If you want to force all the routes to use https you can achieve this by using following code.
if(env('APP_ENV', 'production') == 'production') { // use https only if env is production
\URL::forceScheme('https')
}
The above should solve your problem as all contents now will load from https.
If I change validate by validator->fails return redirect..... I get error because login want an instance of $user and I send a response.
This defaults work well but not for me
public function create(array $input)
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => $this->passwordRules(),
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['required', 'accepted'] : '',
])->validate();
return User::create([
'name' => $input['name'],
'email' => $input['email'],
'password' => Hash::make($input['password']),
]);
}
Thats give me a:
Illuminate\Auth\SessionGuard::login(): Argument #1 ($user) must be of type Illuminate\Contracts\Auth\Authenticatable, Illuminate\Http\RedirectResponse given, called in ....endor/laravel/fortify/src/Http/Controllers/RegisteredUserController.php on line 57
public function create(array $input)
{
$validator = Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => $this->passwordRules(),
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['required', 'accepted'] : '',
]);
if($validator->fails()) {
return Redirect::to(URL::previous() . "#my-anchor")->withInput()->with('error', $validator->messages()->first());
} //Thats I want
return User::create([
'name' => $input['name'],
'email' => $input['email'],
'password' => Hash::make($input['password']),
]);
}
I don't did this before but maybe you can find the way to customize it. The CreateNewUser is called in the RegisteredUserController's store method, and the first return an User's instance. So in this you can
if($validation->fails())
return $validation->messages()->first();
and in the store method
public function store(Request $request, CreatesNewUsers $creator): RegisterResponse
{
$user = $creator->create($request->all()));
if($user instanceof User::class) {
event(new Registered($user);
$this->guard->login($user);
return app(RegisterResponse::class);
} else
return Redirect::to(URL::previous()."#my-anchor")->withInput()->with('error', $user);
}
Try this, but I suggest you if works extends this Register controller and just modify this store method
User password changes in Laravel 8 after a period of time post logout, maybe a day or more. When I look into the database, the password hash has changed. I used the default Laravel authentication and had this issue, so I wrote the login code below, but still, I have the issue.
LoginController
public function login(Request $request)
{
$email_username = filter_var($request->username, FILTER_VALIDATE_EMAIL) ?
'email' : 'username';
$request->merge([$email_username => $request->username]);
if (Auth::attempt($request->only($email_username, 'password'))) {
return redirect()->intended($this->redirectTo);
} else {
return view('auth.login')
->with('these credetials do not match our records.');
}
$user = User::where($email_username, $request->username)->get();
if ($user && Hash::check($request->password, $user->password)) {
$request->session()->regenerate();
auth()->login($user);
return redirect()->intended($this->redirectTo);
}
return redirect()->back();
}
User Model
class User extends Authenticatable
{
use HasFactory, Notifiable;
public function partners()
{
return $this->hasMany('App\Models\partner');
}
protected $fillable = [
'username',
'profilepic',
'firstname',
'lastname',
'password',
'email',
'title',
'phone',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
}
and this is the method that registers user.
public function store(Request $request)
{
$request->validate([
'username' => ['required', 'string', 'max:255', 'unique:users'],
'profilepic' => ['required', 'image', 'mimes:jpeg,png,jpg,gif,svg,ico', 'max:2048'],
'firstname' => ['required', 'string', 'max:255'],
'lastname' => ['required', 'string', 'max:255'],
'password' => ['required', 'string', 'min:8'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'title' => ['required', 'string', 'max:255'],
'phone' => ['required', 'min:10'],
]);
if ($request->profilepic != null) {
$profilepic = $request->firstname . ' ' . $request->lastname . '.' . $request->profilepic->extension();
$request->profilepic->move(public_path('/global_assets/images/users/'), $profilepic);
}
$user = new User([
'username' => $request->get('username'),
'profilepic' => $profilepic,
'firstname' => $request->get('firstname'),
'lastname' => $request->get('lastname'),
'password' => Hash::make($request->get('password')),
'email' => $request->get('email'),
'title' => $request->get('title'),
'phone' => $request->get('phone'),
'isAdmin' => $request->get('isAdmin'),
'isActive' => $request->get('isActive'),
]);
$user->save();
return redirect()->back()->with('success', 'New user has been created.');
}
I hope you can help me, I wanna customize the registercontroller from Laravel, I have this, but after the user is registered send me a JSON of data, how can I do for don't send me the JSON and redirect to the HomeController.
Thanks.
PD. Sorry for my English.
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => ['required', 'string', 'max:255'],
'nombre' => ['required', 'string', 'max:255','unique:users'],
'telefono' => ['required', 'numeric', 'max:99999999', 'min:00000000'],
'direccion' => ['required', 'string', 'max:255'],
'sueldo' => ['numeric','min:0.01','max:0.99'],
//'foto' => ['string', 'max:255'],
'email' => ['string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:4', 'confirmed'],
]);
if ($request->hasFile('foto')) {
$request = request();
$file = $request->file('foto');
$nom_imagen = time().".".$file->getClientOriginalExtension();
$upload_path = 'imagenes/';
$profile_image_url = $upload_path . $nom_imagen;
$success = $file->move($upload_path, $nom_imagen);
} else {
$nom_imagen = '';
}
return User::create([
'name' => $request->input('name'),
'nombre' => $request->input('nombre'),
'telefono' => $request->input('telefono'),
'direccion' => $request->input('direccion'),
'sueldo' => $request->input('sueldo'),
'email' => $request->input('email'),
'foto' => $nom_imagen,
'password' => Hash::make($request['password']),
return redirect()->action('HomeController#index'),
]);
}
Laravel 5.5: Execute a method before registration
HomeController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
return view('index');
}
}
You are returning the return value of User::create() which will be a User object which gets converted to json when returned as a response.
Also since your HomeController is protected by 'auth' middleware you need to login the user before redirecting to '/home'
use Illuminate\Support\Facades\Auth;
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => ['required', 'string', 'max:255'],
'nombre' => ['required', 'string', 'max:255','unique:users'],
'telefono' => ['required', 'numeric', 'max:99999999', 'min:00000000'],
'direccion' => ['required', 'string', 'max:255'],
'sueldo' => ['numeric','min:0.01','max:0.99'],
//'foto' => ['string', 'max:255'],
'email' => ['string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:4', 'confirmed'],
]);
if ($request->hasFile('foto')) {
$request = request();
$file = $request->file('foto');
$nom_imagen = time().".".$file->getClientOriginalExtension();
$upload_path = 'imagenes/';
$profile_image_url = $upload_path . $nom_imagen;
$success = $file->move($upload_path, $nom_imagen);
} else {
$nom_imagen = '';
}
$user = User::create([
'name' => $request->input('name'),
'nombre' => $request->input('nombre'),
'telefono' => $request->input('telefono'),
'direccion' => $request->input('direccion'),
'sueldo' => $request->input('sueldo'),
'email' => $request->input('email'),
'foto' => $nom_imagen,
'password' => Hash::make($request['password']),
]);
Auth::guard()->login($user);
return redirect('/home');
}
Move the redirect after create user , try like this
User::create([
'name' => $request->input('name'),
'nombre' =>$request->input('nombre'),
'telefono' => $request->input('telefono'),
'direccion' => $request->input('direccion'),
'sueldo' => $request->input('sueldo'),
'email' => $request->input('email'),
'foto' => $nom_imagen,
'password' => Hash::make($request['password'])
]);
return redirect()->action('HomeController#index'),
I'm using oauth2 and my table users is "coUsers" . I added this in my User Model
App\User
protected $table = 'coUsers';
public function getAuthPassword()
{
return $this->pass;
}
AuthController
public function login(Request $request)
{
$request->validate([
'usuario' => 'required|string|email',
'clave' => 'required|string',
//'remember_me' => 'boolean'
]);
$credentials = [
'usuario' => $request->get('usuario'),
'password' => $request->get('clave'),
];
if(!Auth::attempt($credentials)){
return response()->json([
'message' => 'Unauthorized'
], 401);
}
$user = $request->user();
$tokenResult = $user->createToken('Personal Access Token');
$token = $tokenResult->token;
if ($request->remember_me)
$token->expires_at = Carbon::now()->addWeeks(1);
$token->save();
return response()->json([
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse($tokenResult->token->expires_at)->toDateTimeString()
]);
}
public function firstLogin(Request $request)
{
$request->validate([
'usuario' => 'required|string|email|unique:users',
'clave' => 'required|string',
'nuevaClave' => 'required|string'
]);
$user = User::where('usuario', $request['usuario'])
->where('clave', $request['clave'])
->first();
$user->clave = bcrypt($request['nuevaClave']);
$user->first_login = false;
$user->save();
return response()->json([
$user->toArray()
]);
}
Auth login works OK, but I want to use User::where in firstLogin.... I get this error:
Illuminate\Database\QueryException: SQLSTATE[42703]: Undefined column: 7 ERROR: column "usuario" does not exist
LINE 1: select count() as aggregate from "users" where "usuario" = ...
^ (SQL: select count() as aggregate from "users" where "usuario" = xxxxx#gmail.com) in file \vendor\laravel\framework\src\Illuminate\Database\Connection.php on line 669
Look in the users table instead of using the table that I indicated in the model.
You may change 'usuario' => 'required|string|email|unique:users', to 'usuario' => 'required|string|email|unique:coUsers', in your firstLogin method
You may also change this 'unique:users' in validator method inside your App\Http\Controllers\Auth\RegisterController
'email' => ['required', 'string', 'email', 'max:255', 'unique:users']
to
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:coUsers'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}