Using named routes in protected methods in Laravel Controller - php

In my LoginController I have:
protected $redirectTo = '';
I then do this:
public function boot()
{
Parent::boot();
$this->redirectTo = route('org.home');
$this->logoutTo = route('user.login');
}
But in a method in the controller I check and I get a BLANK value from $this->redirectTo
protected function authenticated(Request $request, $user)
{
dd($this->redirectTo);
}
How do I make the value of this variable dynamic and use the route name to assign its value?
Here is my whole controller based on the comments below:
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Which Authentication Guard we are working with
*
* #var string
*/
protected $guard = 'user';
/**
* URI where we redirect to after registration
*
* #var string
*/
protected $redirectTo = '';
/**
* URI where we redirect to after logout
*
* #var string
*/
protected $logoutTo = '';
/**
* LoginController constructor.
*/
public function __construct()
{
//
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
Parent::boot();
$this->redirectTo = route('org.home');
$this->logoutTo = route('user.login');
}
/**
* Show the application's login form.
*
* #return \Illuminate\Http\Response
*/
public function showLoginForm()
{
return view('auth.user.main.login');
}
/**
* Log the user out of the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
Auth::guard($this->guard)->logout();
$request->session()->flush();
$request->session()->regenerate();
if ($request->ajax()) {
return response()->json([
'type' => 'success',
'message' => trans('auth.logout_ok')
]);
} else {
return redirect($this->logoutTo ?: '/');
}
}
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
// If this user belongs to a partner
if ($user->isPartner()) {
// And the partner is active, then continue
if (!$user->partner->isActive()) {
// Else respond with an error
$error = [
'type' => 'error',
'message' => trans('messages.partner_inactive')
];
if ($request->ajax()) {
return response()->json($error);
} else {
return redirect()->back()->withErrors($error);
}
}
}
dd($this->redirectTo);
// Set up the user's session
$this->setupSession();
if ($request->ajax()) {
return response()->json([
'type' => 'success',
'user' => auth()->check(),
'intended' => $this->redirectPath(),
'message' => trans('auth.logout_ok')
]);
} else {
return redirect()->intended($this->redirectPath());
}
}
/**
* Send the response after the user was authenticated.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
if ($this->authenticated($request, $this->guard()->user())) {
return true;
} else {
if ($request->ajax()) {
return response()->json([
'type' => 'error',
'user' => auth()->check(),
'intended' => $this->redirectPath(),
'message' => trans('auth.not_login')
]);
} else {
return redirect()->intended($this->redirectPath());
}
}
}
/**
* Get the failed login response instance.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse
*/
protected function sendFailedLoginResponse(Request $request)
{
$errors = [$this->username() => trans('auth.failed')];
if ($request->expectsJson()) {
return response()->json($errors, 422);
}
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors($errors);
}
/**
* Set up all session variables here
*/
private function setupSession()
{
// session()->put('user', Auth::user());
}
}

I had to put my assignments here
public function __construct()
{
$this->redirectTo = route('org.home');
$this->logoutTo = route('user.login');
}

Related

Laravel multiple policies always authenticated?

I'm using Laravel 9 with the Laravel Spatie Permissions package. I have users and roles in my system. Users have roles, and depending on their permissions on their role they either can or can't create new users / new roles etc.
I've set up my UserPolicy and RolePolicy, and am passing my User model to each since it's the user that needs to be checked against what permissions they have, then in the controller of my choice, such as my RoleController I run:
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$this->authorize('viewAny', User::class);
$roles = Role::with('permissions')->get();
if (!$roles || count($roles) <= 0) {
return response()->json([
'message' => 'No roles found'
], 404);
}
return response()->json([
'roles' => $roles
], 200);
}
Strangely, if I edit my RolePolicy's viewAny permission and return false, I'm still able to see the data? I shouldn't be. what am I missing?
Here's my RolePolicy
<?php
namespace App\Policies\UserManagement;
use Spatie\Permission\Models\Role;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class RolePolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view any models.
*
* #param \App\Models\User $user
* #return \Illuminate\Auth\Access\Response|bool
*/
public function viewAny(User $user)
{
// TODO: if I return false I still have access?
if ($user->can('role_index')) {
return true;
}
}
/**
* Determine whether the user can view the model.
*
* #param \App\Models\User $user
* #return \Illuminate\Auth\Access\Response|bool
*/
public function view(User $user)
{
if ($user->can('role_show')) {
return true;
}
}
/**
* Determine whether the user can create models.
*
* #param \App\Models\User $user
* #return \Illuminate\Auth\Access\Response|bool
*/
public function create(User $user)
{
if ($user->can('role_store')) {
return true;
}
}
/**
* Determine whether the user can update the model.
*
* #param \App\Models\User $user
* #return \Illuminate\Auth\Access\Response|bool
*/
public function update(User $user)
{
if ($user->can('role_update')) {
return true;
}
}
/**
* Determine whether the user can delete the model.
*
* #param \App\Models\User $user
* #return \Illuminate\Auth\Access\Response|bool
*/
public function delete(User $user)
{
if ($user->can('role_destroy')) {
return true;
}
}
}
And my AuthServiceProvider:
<?php
namespace App\Providers;
use App\Models\User;
use Spatie\Permission\Models\Role;
use App\Policies\UserManagement\UserPolicy;
use App\Policies\UserManagement\RolePolicy;
use Illuminate\Support\Facades\Gate;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The model to policy mappings for the application.
*
* #var array<class-string, class-string>
*/
protected $policies = [
User::class => UserPolicy::class,
User::class => RolePolicy::class,
];
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
ResetPassword::createUrlUsing(function ($user, string $token) {
$frontendUrl = trim(rtrim(config('lespro.frontend_url'), '/'));
return $frontendUrl . '/account/reset/?email=' . $user->email . '&token=' . $token;
});
// Implicitly grant "super_admin" role all permissions
// This works in the app by using gate-related functions like auth()->user->can() and #can()
Gate::before(function ($user, $ability) {
return $user->hasRole('super_admin') ? true : null;
});
}
}

How to override method in Laravel

I`m trying override "public function sendCode()" to use it in LoginController from below TokenModel.
have done more than tripled confirmed that loading and calling TokenModel from LoginController as an instance is succeed but "public function sendCode()" is not included with TokenModel.
would be very helpful if anyone knows what happens here and tell me what I should code.
=======================TokenModel=========================
<?php
namespace App;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
class Token extends Model
{
const EXPIRATION_TIME = 15; // minutes
protected $fillable = [
'code',
'user_id',
'used'
];
public function __construct(array $attributes = [])
{
if (! isset($attributes['code'])) {
$attributes['code'] = $this->generateCode();
}
parent::__construct($attributes);
}
/**
* Generate a six digits code
*
* #param int $codeLength
* #return string
*/
public function generateCode($codeLength = 4)
{
$min = pow(10, $codeLength);
$max = $min * 10 - 1;
$code = mt_rand($min, $max);
return $code;
}
/**
* User tokens relation
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* Send code to user
*
* #return bool
* #throws \Exception
*/
public function sendCode()
{
if (! $this->user) {
throw new \Exception("No user attached to this token.");
}
if (! $this->code) {
$this->code = $this->generateCode();
}
try {
app('twilio')->messages->create($this->user->getPhoneNumber(),
['from' => env('TWILIO_NUMBER'), 'body' => "Your verification code is {$this->code}"]);
} catch (\Exception $ex) {
return false; //enable to send SMS
}
return true;
}
/**
* True if the token is not used nor expired
*
* #return bool
*/
public function isValid()
{
return ! $this->isUsed() && ! $this->isExpired();
}
/**
* Is the current token used
*
* #return bool
*/
public function isUsed()
{
return $this->used;
}
/**
* Is the current token expired
*
* #return bool
*/
public function isExpired()
{
return $this->created_at->diffInMinutes(Carbon::now()) > static::EXPIRATION_TIME;
}
}
=======================LoginController=========================
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Token;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Lang;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
}
/**
* Handle a login request to the application.
*
* #param \Illuminate\Http\Request $request
* #return mixed
*/
public function login(Request $request)
{
$this->validateLogin($request);
//retrieveByCredentials
if ($user = app('auth')->getProvider()->retrieveByCredentials($request->only('email', 'password'))) {
$token = Token::create([
'user_id' => $user->id
]);
if ($token->sendCode()) {
session()->set("token_id", $token->id);
session()->set("user_id", $user->id);
session()->set("remember", $request->get('remember'));
return redirect("code");
}
$token->delete();// delete token because it can't be sent
return redirect('/login')->withErrors([
"Unable to send verification code"
]);
}
return redirect()->back()
->withInputs()
->withErrors([
$this->username() => Lang::get('auth.failed'),
]);
}
/**
* Show second factor form
*
* #return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
*/
public function showCodeForm()
{
if (! session()->has("token_id")) {
return redirect("login");
}
return view("auth.code");
}
/**
* Store and verify user second factor.
*/
public function storeCodeForm(Request $request)
{
// throttle for too many attempts
if (! session()->has("token_id", "user_id")) {
return redirect("login");
}
$token = Token::find(session()->get("token_id"));
if (! $token ||
! $token->isValid() ||
$request->code !== $token->code ||
(int)session()->get("user_id") !== $token->user->id
) {
return redirect("code")->withErrors(["Invalid token"]);
}
$token->used = true;
$token->save();
$this->guard()->login($token->user, session()->get('remember', false));
session()->forget('token_id', 'user_id', 'remember');
return redirect('home');
}
}

login returns error invalid credentials even the given credentials is correct

I'm trying to modify the default authentication to tailor my needs. I have this requirements like a user should be able to login using either user name or email but it always returns invalid credentials error even if the given credentials are correct, please refer to the code below:
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
trait AuthenticatesUsers
{
use RedirectsUsers, ThrottlesLogins;
/**
* Show the application's login form.
*
* #return \Illuminate\Http\Response
*/
public function showLoginForm()
{
return view('auth.login');
}
/**
* Handle a login request to the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
*/
public function login(Request $request)
{
$this->validateLogin($request);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
/**
* Validate the user login request.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required|string',
'password' => 'required|string',
]);
}
/**
* Attempt to log the user into the application.
*
* #param \Illuminate\Http\Request $request
* #return bool
*/
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->has('remember')
);
}
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(Request $request)
{
// return $request->only($this->username(), 'password');
if(filter_var($request->username_email, FILTER_VALIDATE_EMAIL) ){
return $request->only('email', 'password');
}else{
return $request->only('username', 'password');
}
}
/**
* Send the response after the user was authenticated.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user())
?: redirect()->intended($this->redirectPath());
}
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
//
return response()->json([ 'message' => 'authenticated']);
}
/**
* Get the failed login response instance.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse
*/
protected function sendFailedLoginResponse(Request $request)
{
$errors = [$this->username() => trans('auth.failed')];
if ($request->expectsJson()) {
return response()->json($errors);
}
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors($errors);
}
/**
* Get the login username to be used by the controller.
*
* #return string
*/
public function username()
{
return 'username_email';
}
/**
* Log the user out of the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->flush();
$request->session()->regenerate();
return redirect('/');
}
/**
* Get the guard to be used during authentication.
*
* #return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard();
}
}
Inside credentials(), I check if its an username or email first and then return the corresponding database column, but it looks like it doesn't work at all. Any ideas, help please?
Your method:
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required|string',
'password' => 'required|string',
]);
}
With username() returning username_email seems incoherent. I think what you looking for is required_without_all:
protected function validateLogin(Request $request)
{
$this->validate($request, [
'username' => 'required_without_all:email|string',
'email' => 'required_without_all:username|string',
'password' => 'required|string',
]);
}
So username will be required when email is not present and vice versa.

Login by Email/Phone number in Laravel Auth()

I am using
Route::auth();
for making user login in Laravel.
There are multiple phones linked to a user and saved in table:phones.
Tables are
users : id,email,password
phones: id,user_id,phone_number
How to make user login with both Email/Phones and password
In App\Traits\Auth, create a file named LoginUser.php.
<?php
namespace App\Traits\Auth;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
trait LoginUser
{
/**
* Handle a Authenticates the User.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function login(Request $request)
{
$this->validateLogin($request);
if ($this->attemptLogin($request)) {
return $this->successfulLogin($request);
}
return $this->failedLogin($request);
}
/**
* Validate the user login request.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
'username' => 'required',
'password' => 'required',
]);
}
/**
* Attempt to log the user into the application.
*
* #param \Illuminate\Http\Request $request
* #return bool
*/
protected function attemptLogin(Request $request)
{
//Try with email AND username fields
if (Auth::attempt([
'phone' => $request['username'],
'password' => $request['password']
],$request->has('remember'))
|| Auth::attempt([
'email' => $request['username'],
'password' => $request['password']
],$request->has('remember'))){
return true;
}
return false;
}
/**
* This is executed when the user successfully logs in
*
* #var Request $request
* #return Reponse
*/
protected function successfulLogin(Request $request){
return redirect($this->redirectTo);
}
/**
* This is executed when the user fails to log in
*
* #var Request $request
* #return Reponse
*/
protected function failedLogin(Request $request){
return redirect()->back()->withErrors(['password' => 'You entered the wrong username or password']);
}
}
Then in
App\Http\Controllers\Auth
rewrite (or create) LoginController.php and paste this
<?php
namespace App\Http\Controllers\Auth;
use App\Traits\Auth\LoginUser;
use App\Http\Controllers\Controller;
class LoginController extends Controller
{
use LoginUser;
/**
* Where to redirect users after registration.
*
* #var string | URL
*/
protected $redirectTo = '/mPanel';
/**
* Displays login page
*
* #return \Illuminate\Http\Response
*/
public function show(){
return response()->view('LOGIN PAGE HERE');
}
}
Finally in your routes file, add these routes:
Route::get('login', 'Auth\LoginController#show');
Route::post('login', 'Auth\LoginController#login');

ErrorException in HomeController.php line 27: Trying to get property of non-object

I'm on Laravel 5.3 and I'm using view and I intend to share a variable globally to all of my views and this global variable contents the user's info who is currently logged in.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use View;
//use models
use App\profile;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
View::share('user_info',profile::where('username',Auth::user()->username)->get());
}
public function index()
{
$current_page = 'home';
return view('pages.home');
}
}
but unfortunately it gives me this error
ErrorException in HomeController.php line 27: Trying to get property
of non-object
and the line 27 is this line
View::share('user_info',profile::where('username',Auth::user()->username)->first());
it seem's like the problem is 'Auth::user()->username' because If I manually specify the username, it gives me the collection I need.
Any ideas, help please?
here's my AuthenticatesUsers.php which I used to modify the authentication stuffs.
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Lang;
trait AuthenticatesUsers
{
use RedirectsUsers, ThrottlesLogins;
/**
* Show the application's login form.
*
* #return \Illuminate\Http\Response
*/
public function showLoginForm()
{
return view('auth.login');
}
/**
* Handle a login request to the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function login(Request $request)
{
$this->validateLogin($request);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
$credentials = $this->credentials($request);
if ($this->guard()->attempt($credentials, $request->has('remember'))) {
return $this->sendLoginResponse($request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
/**
* Validate the user login request.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required', 'password' => 'required',
]);
}
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(Request $request)
{
return $request->only($this->username(), 'password');
}
/**
* Send the response after the user was authenticated.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user())
?: redirect()->intended($this->redirectPath());
}
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
//check user role
return redirect('/app/system/dashboard');
}
/**
* Get the failed login response instance.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
protected function sendFailedLoginResponse(Request $request)
{
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors([
$this->username() => Lang::get('auth.failed'),
]);
}
/**
* Get the login username to be used by the controller.
*
* #return string
*/
public function username()
{
return 'username';
}
/**
* Log the user out of the application.
*
* #param Request $request
* #return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->flush();
$request->session()->regenerate();
return redirect('/');
}
/**
* Get the guard to be used during authentication.
*
* #return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard();
}
}
It seems you're running this code when user is not logged in, so you could do a check:
View::share('user_info', auth()->check() ? profile::where('username', auth()->user()->username)->first() : null);
This code will return profile or null if user is not logged in.
change this
if ($this->guard()->attempt($credentials, $request->has('remember'))) {
return $this->sendLoginResponse($request);
}
to
if (Auth::attempt($credentials, $request->has('remember'))) {
return $this->sendLoginResponse($request);
}

Categories