Laravel Middleware Too few arguments to function error - php

I am trying to setup a middleware to check if inputs are empty on form submit for updating a users settings, and if so to return them back to the same page with an error. When I set it up, it gives me the error
Too few arguments to function App\Http\Middleware\AdminUserUpdate::handle(), 2 passed in /var/www/market/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php on line 167 and exactly 3 expected
It seems to be the id I pass through, here is the rest of my code
Middleware:
public function handle(Request $request, Closure $next, $id)
{
if($request->input('username') == NULL) {
return redirect()->route('admin.members.view', $id)->with('error', 'You must enter a username for this user in order to update their account!');
} elseif($request->input('email') == NULL) {
return redirect()->route('admin.members.view', $id)->with('error', 'You must enter a email for this user in order to update their account!');
} elseif($request->input('admin') == NULL) {
return redirect()->route('admin.members.view', $id)->with('error', 'You must select whether this user is a root admin or not in order to update their account!');
} elseif($request->input('banned') == NULL) {
return redirect()->route('admin.members.view', $id)->with('error', 'You must select whether this user is banned or not in order to update their account!');
} elseif($request->input('role') == NULL) {
return redirect()->route('admin.members.view', $id)->with('error', 'You must select a role for this user in order to update their account!');
}
return $next($request);
}
Kernel:
'AdminUserUpdate' => \App\Http\Middleware\AdminUserUpdate::class,
Route:
Route::middleware(['AdminUserUpdate'])->group(function () {
Route::post('/app/members/{id}/submit', 'App\Http\Controllers\Admin\Members\IndexController#Submit')->name('admin.members.submit');
});
I have the ID passed through so I can return them back to the view page for the specific users id, but it doesnt seem to like that for some reason. Anyone have any thoughts?

Middlewares doesn't read route parameters. Use colon to pass a parameter to the middleware.
Route::middleware(['AdminUserUpdate:123'])->group(function () {
Link to Middleware Parameters docs

I suggest to change the way you validate your fields.
In your case, this command create the form validator file
php artisan make:request UpdateUserRequest
In the file UpdateUserRequest.php
This block have all the rules you want to validate
public function rules()
{
return [
'username' => 'required',
'email' => 'required',
... other fields for validation ...
];
}
and inside the store method in your Controller, only this line is required to manipulate all the data after the validation:
$validated = $request->validated();
and for custom messages, add this into your UpdateUserRequest:
public function messages()
{
return [
'username.required' => 'You must enter a username for this user in order to update their account!',
'email.required' => 'You must enter a email for this user in order to update their account!',
... and other validation messages ...
];
}
For more details and ways to validate your forms, check the link:
Form Request Validation

Related

Check users role Laravel

After a user enters his credential and tries to login and after the user is found, we have a siterole table that will be checked, if the role that the user selected is found in the database "where userID=request and roleType = request" then the login is successful otherwise it fails due to choosing the wrong user role.
The code is simple:
$findrole = $request->role;
$user_id = Auth::user()->id;
$userrole = DB::table('siterole')->where('role_id' ,'=',$findrole)->where('user_id' ,'=', $user_id)->get();
if(!empty($userrole)) {
make it login
}
else{
redirect it with a fail login
}
By failed login I mean no session should be set, where I tried this code was in
vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php
BUT when the "role_id" is not found for that "user_Id", the user is logged in and redirected to the wrong page!
Edit the function Im putting my code in is this :
public function login(Request $request)
{
$this->validateLogin($request);
$throttles = $this->isUsingThrottlesLoginsTrait();
if ($throttles && $lockedOut = $this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
$credentials = $this->getCredentials($request);
if (Auth::guard($this->getGuard())->attempt($credentials, $request->has('remember'))) {
//MYCODE GOES BETWEEN THESE LINES
if its not empty return the below code
return $this->handleUserWasAuthenticated($request, $throttles);
}
if ($throttles && ! $lockedOut) {
$this->incrementLoginAttempts($request);
}
//if its empty return to this section
return $this->sendFailedLoginResponse($request);
}
Auth::user()->id returns the user id only when you are authenticated. In line 2 of your example code, when you are creating the $user_id variable you are not authenticated yet so it will always be null. You'll need to get the user_id another way.
Found the solution, so where i was putting my condition is where laravel already returned a login = true, so i cant do anything.
that attemp() is actually attempting the login which is located in :
vendor\laravel\framework\src\Illuminate\Auth\SessionGuard.php
now in attemp function we dont have access to our request but we can pass the User type i call it (role) in function getCredentials which is located in :
vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php
Step 1:
protected function getCredentials(Request $request)
{
//sending role as credential too
// my input name was role
return $request->only($this->loginUsername(), 'password','role');
}
Now since we passed it in attemp() , its the 2nd array of our credentials BUT we have to unset it from the main credentials because laravel will create a where clause for each key in array :
Step 2
public function attempt(array $credentials = [], $remember = false, $login = true)
{
//get the user roll to check if the user has the same role
//else kill him #Stormspirit
$user_role = $credentials['role'];
//as laravel make the where clause for every field we unset it from the array
unset($credentials['role']);
$this->fireAttemptEvent($credentials, $remember, $login);
$this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);
// If an implementation of UserInterface was returned, we'll ask the provider
// to validate the user against the given credentials, and if they are in
// fact valid we'll log the users into the application and return true.
if ($this->hasValidCredentials($user, $credentials)) {
//user credential was valid check the role part
$userrole_finder = DB::table('siterole')->where('role_type',$user_role)->where('user_id',$user->id)->get();
if($userrole_finder==[]) {
$login = false;
return false;
}
if ($login) {
$this->login($user, $remember);
}
return true;
}
All set! dont forget to add use DB; check your user role table and if it was empty make the login false and return false that would do the rest and u will see laravel's invalid credential error.
You can implement this for user type I just called it role.you can also put the user type in a session in handleUserWasAuthenticated function in AuthenticatesUsers.php , exact location described above
protected function handleUserWasAuthenticated(Request $request, $throttles)
{
session(['user_role' => $request->role]);
if ($throttles) {
$this->clearLoginAttempts($request);
}
if (method_exists($this, 'authenticated')) {
return $this->authenticated($request, Auth::guard($this->getGuard())->user());
}
return redirect()->intended($this->redirectPath());
}

how to change the value of a column in laravel on logout

i have a column called active_user to show when a user is online(1). When i log a user in i set the active_user column to 1 but when i log the user out and check active_user it still shows online(1). what i want is that when i click the logout button the aactive_user column will change to offline(0) and also update it to the database. my login is below.
public function postSignIn(Request $request) {
$this->validate($request, [
'email' => 'required',
'password' => 'required'
]);
if(Auth::attempt(['email' => $request['email'], 'password' => $request['password']])) {
$user=User::whereRaw('email=?',[Input::get('email')])->first();
//this is where i set the active_user to 1
$user->active_user=1;
$user->save();
if($user!=null){
switch($user->role_id){
case 1:
if($user->status==0){
session()->flash('flash_message_error', ' Your Account has been deactivated. Contact the administrator');
return Redirect::to('admin/login');
}
return redirect()->route("index");
break;
then below is my logout function
public function LogOut($id) {
$user = User::find($id);
$user->active_user=1;
$user->save();
Auth::logout();
return redirect('admin/login');
}
in the logout function i want to change the active_user back to offline(0) but i keep getting an error "Missing argument 1 for App\Http\Controllers\AdminController::LogOut()"
Your route logout is now expecting an id attribute passed to it. This seems wrong to me as it is the authenticated user that you want to apply this logic to, having to pass their id to logout is unnecessary. For example if your logged in user has an id of 1, to logout with your code they would need to go to a url such as:
http://myapp.app/logout/1
Instead, use the Auth implementation to modify the user.
// Remove requirement for ID as a parameter
public function LogOut() {
$user = Auth::user();
$user->active_user=1;
$user->save();
Auth::logout();
return redirect('admin/login');
}

how to get back to own profile after searching for an invalid username in the URL

I am new to laravel.I have a controller called userController to mangae user in my application.Here i have a user authentication and profile system.It will send the user to its own profile after login.Sometimes user may wish to search for a random username or id field in the url to search for a user.If desired user is found ,their profile info will be shown in the profile section.But if no user is found i want my application to get the current logged in user and show his/her info instead.How i can do that?
if my user name is 'zim' i can write the url mydomain/user/zim ,it will get my profile,But if i search an invalid name say 'zi' mydomain/user/zi , i want my application to return mydomain/user/zim again
All i can manage here is to show a flash message if no user is found.Can't figure out how to retrieve the current logged user.Tried to use the Request class but seems not working
loginUser function():
public function loginUser(Request $request){
$data = $request->all();
$rules = array(
'name' => 'required',
'password'=>'required'
);
// Create a new validator instance.
$validator = Validator::make($data, $rules);
if($validator->fails()){
$errors=$validator->messages();
return redirect()->back()->withErrors($validator);
}else{
if(Auth::attempt(['name'=>$request['name'],'password'=>$request['password']])){
return redirect()->route('user.show',[$request['name']]);
}else{
return redirect()->back()->with('data', 'wrong username or password');
}
}
}
show() method in userController:
public function show($user,Request $request) // tried with Request but failed
{
//
$indicator=is_numeric($user)?'id':'name';
$info=userModel::where($indicator,'=',$user)->get()->first();
if($info){
return View::make('user.show')->with('user',$info);
}else{
session()->flash('message','no user');
return View::make('user.show');
}
}
You just need to change your show method slightly.
public function show($user,Request $request)
{
$indicator=is_numeric($user)?'id':'name';
$info=userModel::where($indicator,'=',$user)->get()->first();
if(empty($info)){
return View::make('user.show')->with('user',$info);
}else{
session()->flash('message','no user but here is your info :)');
return View::make('user.show')->with('user', Auth::user());
}
}
Edited for better logic.
public function show($username)
{
$info = userModel::where(username, $username)->get()->first();
if($info != null){
return View::make('user.show')->with('user', $info);
}
else{
session()->flash('message','No user found! But here is your info!');
return View::make('user.show')->with('user',Auth::user());
}
}
Here is a much simplified option. (Always allow the URL to collect only one type instead of checking if its id or username)

how to pass parameter to show() method in resource controller from another function

I know that the route name for show($id) method is some_name/parameter.Here i have a login authentication mechanism and i want to show the user profile if the user passed the authentication.I have a function called loginUser() inside my userController.I want to redirect the user to user.show route on successful login.But i am not sure how to pass the parameter value to show method.Currently i am getting the error:
Missing required parameters for [Route: user.show] [URI: user/{user}].
loginUser() function:
public function loginUser(Request $request){
$data = $request->all();
$rules = array(
'name' => 'required',
'password'=>'required'
);
// Create a new validator instance.
$validator = Validator::make($data, $rules);
if($validator->fails()){
$errors=$validator->messages();
return redirect()->back()->withErrors($validator);
}else{
if(Auth::attempt(['name'=>$request['name'],'password'=>$request['password']])){
return redirect()->route('user.show')->with('name',$request['name']); // pass control to show() function
}else{
return redirect()->back()->with('data', 'wrong username or password');
}
}
}
show() method in userController:
public function show($user)
{
//
$info=userModel::where('id','=',$user)->get(array('name'));
return View::make('user.show')->with('name',$info);
}
Your route user.show needs an id to determine which user to show. Like this:
redirect()->route('user.show', [$userId])->with(...);
If for example $userId is 1, this would resolve to the URI: user/1
If you want to show the user index, that's a different route.
Try this
redirect()->route('user.show', [$userId]);
you don't use $name in controller. remove with in redirect

Input validation in laravel?

I have a Input validation to change user password, when i tried to submit the form i got always an error that the new password and confirm password are not matched even, this is my post action :
public function doChangePassword()
{
if(Auth::check())
{
$validator = Validator::make(Input::all(), User::$updatePasswordRules);
// if the validator fails, redirect back to the form
if ($validator->fails()) {
return Redirect::to('change-password')->with('message', 'The following errors occurred')->withErrors($validator)->withInput();
} else {
// store
$user = User::find(Auth::user()->id);
if(Auth::user()->password==Input::get('new_password')){
$user->password = Hash::make(Input::get('new_password'));
$user->save();
}
else{
return Redirect::to('change-password')->with('message', 'The password is not correct');
}
// redirect
Session::flash('message', 'Successfully updated password!');
return Redirect::to('login');
}
}
else{
return Redirect::to('login');
}
}
this is my rules :
public static $updatePasswordRules = array(
'password'=>'required|alpha_num|between:6,12',
'new_password'=>'required|alpha_num|between:6,12|confirmed',
'password_confirmation'=>'required|alpha_num|between:6,12'
);
so please if someone has an idea i will be very appreciative
It's because Laravel expects (for your specific case) confirmed field to be named new_password_confirmation
From doc "The field under validation must have a matching field of foo_confirmation. For example, if the field under validation is password, a matching password_confirmation field must be present in the input."
Thus rules should look like (also change input name in form):
public static $updatePasswordRules = array(
'password'=>'required|alpha_num|between:6,12',
'new_password'=>'required|alpha_num|between:6,12|confirmed',
'new_password_confirmation'=>'required|alpha_num|between:6,12'
);
Or you can do it with same validation rule (if don't want to update form inputs):
public static $updatePasswordRules = array(
'password'=>'required|alpha_num|between:6,12',
'new_password'=>'required|alpha_num|between:6,12|same:password_confirmation',
'password_confirmation'=>'required|alpha_num|between:6,12'
);

Categories