Restricting not logged users access to admin panel in Laravel - routing issue - laravel

I've started creating my own very simple blog application, which would consist of main page with posts and admin panel accesible only for me. I don't want viewers to have access to login page, it should be just for one user - admin.
I already have admin panel from which I can create, edit, view and delete posts stored in mySQL database, also posts are displayed on main page. My problem is that I am strugling with securing the admin panel from not logged users.
How should I do this, idea is: if you are logged in - you are admin, you can access admin panel which views are stored in views/admin, if you are not - you can only see posts beeing displayed on main page in views folder.
publicHomePageTemplate.blade.php (piece responsible for displaying posts)
#foreach($articles as $article)
<div class="well well-lg">
<h3>{{$article->title}}</h3>
<p>{{$article->body}}</p>
</div>
#endforeach
Article Controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Article;
class ArticleController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function publicHomePage()
{
$articles = Article::paginate(4);
return view('articles/publicHomePageTemplate', ['articles'=>$articles]);
}
public function index()
{
$articles = Article::latest()->paginate(5);
return view('admin.index',compact('articles'))
->with('i', (request()->input('page', 1) - 1) * 5);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('admin.create');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
request()->validate([
'title' => 'required',
'body' => 'required',
]);
Article::create($request->all());
return redirect()->route('admin.index')
->with('success','Article created successfully');
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
$article = Article::find($id);
return view('admin.show',compact('article'));
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
$article = Article::find($id);
return view('admin.edit',compact('article'));
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
request()->validate([
'title' => 'required',
'body' => 'required',
]);
Article::find($id)->update($request->all());
return redirect()->route('admin.index')
->with('success','Article updated successfully');
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
Article::find($id)->delete();
return redirect()->route('admin.index')
->with('success','Article deleted successfully');
}
}
So far I've started realising authentication system with php artisan:make auth
Any ideas how to solve this

Create a middleware that blocks users that should not access admin
This goes in the Http Kernel in $middlewareGroups
'admin' => [
'web',
\App\Http\Middleware\Permissions\AdminChecker::class,
],
then you create a middleware that checks the current user
public function handle($request, Closure $next)
{
$user = $request->user();
if (!$user || !$user->isAdmin()) {
throw new AuthenticationException;
}
return $next($request);
}
Then make sure that your admin routes are using the admin group
In the RouteServiceProvider
Route::group([
'middleware' => 'admin',
'namespace' => $this->namespace.'\Admin',
'prefix' => 'admin',
], function ($router) {
require base_path('routes/admin.php');
});
then you put your admin routes in 'routes/admin.php

if you add the field "role" in your table then try if(Auth::user()->role == 'admin'){}else{}. you can also use this code in your blade file like #if().

Related

Laravel: How do I raise a 404 error instead of a 50X error when ID for resource is non-integer

I created a simple crud in Laravel, but I'm having a problem:
I am using Illuminate\Support\Facades\Route::resource method, this is my routes/web.php:
<?php
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
Route::get('/', function () {
return Inertia::render('Welcome', [
'canLogin' => Route::has('login'),
'canRegister' => Route::has('register'),
'laravelVersion' => Application::VERSION,
'phpVersion' => PHP_VERSION,
]);
});
Route::get('dashboard', [App\Http\Controllers\PageController::class, 'dashboard'])
->middleware('auth:sanctum')
->name('dashboard');
Route::resource('notes', App\Http\Controllers\NoteController::class)
->middleware('auth:sanctum');
app/Http/Controllers/NoteController.php:
<?php
namespace App\Http\Controllers;
use App\Models\Note;
use Illuminate\Http\Request;
use Inertia\Inertia;
class NoteController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(Request $request)
{
if ($request->q) {
return Inertia::render('Notes/Index', [
'notes' => Note::where('title', 'ilike', "%$request->q%")->get(),
]);
}
return Inertia::render('Notes/Index', [
'notes' => Note::all()
]);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return Inertia::render('Notes/Create', [
'note' => new Note()
]);
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$note = Note::create($request->validate([
'title' => 'required',
'content' => 'required',
]));
return redirect()->route('notes.show', $note)->with('success', 'Nota creada');
}
/**
* Display the specified resource.
*
* #param \App\Models\Note $note
* #return \Illuminate\Http\Response
*/
public function show(Note $note)
{
return Inertia::render('Notes/Show', compact('note'));
}
/**
* Show the form for editing the specified resource.
*
* #param \App\Models\Note $note
* #return \Illuminate\Http\Response
*/
public function edit(Note $note)
{
return Inertia::render('Notes/Edit', compact('note'));
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Models\Note $note
* #return \Illuminate\Http\Response
*/
public function update(Request $request, Note $note)
{
$request->validate([
'title' => 'required',
'content' => 'required',
]);
$note->update($request->all());
return redirect()->route('notes.show', $note)->with('success', 'Nota actualizada');
}
/**
* Remove the specified resource from storage.
*
* #param \App\Models\Note $note
* #return \Illuminate\Http\Response
*/
public function destroy(Note $note)
{
$note->delete();
return redirect()->route('notes.index')->with('success', 'Nota eliminada');
}
}
When I go to /notes/a where 'a' is supposed to be the index of the note I want to see, I get a 500 error:
SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for type bigint: "a"
select * from "notes" where "id" = a limit 1
At this point, none of my code has yet run. How can I catch this error to raise a 404 error instead?
you can use firstOrFail() or findOrFail example code below
public function find(Request $request){
return Note::findOrFail($request->id);
}
You can use abort(404) which abort your code if no data found.
public function findNote($id)
{
$note = Note::find($id)
if($note == null)
{
abort(404);
}
}
you can use try catch block to modify the response
public function whatEverMyMethodIs( Request $request ) {
try {
return ModeL::find( $request->input('id') );
} catch (\Throwable $th) {
return response()->json(['message' => $th->getMessage()], 404 );
}
}
Since you're using the built-in resource controller, the following URIs, among others, will have been created and model binding happens. If the parameter doesn't fit the id's type it will error out.
GET /notes/{note}
GET /notes/{note}/edit
I have not found a way to modify the request validation when model binding happens. If you wish to customise the behaviour, you can do so by leaving the show and edit functions out of the route resource declaration and writing custom endpoints listed above.
routes/web.php
Route::resource('notes', NoteController::class)->except([
'show', 'edit'
]);
Route::get('/notes/{note}', [
'as' => 'notes.show',
'uses' => '\App\Http\Controllers\NoteController#show',
]);
app/Http/Controllers/NoteController.php
use Illuminate\Http\Request;
...
public function show(Request $request)
{
$noteId = $request->note;
...
}
You can perform the validation by switching Request to a custom request which inherits FormRequest.
More information can be found here:
https://laravel.com/docs/9.x/validation#form-request-validation

Laravel Login Controller - Direct to Admin or User Routes

I have a Laravel8 Project where I am doing everything from scratch so i can learn the system (newbie) - I have a LoginController with the code
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class LoginController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
// Show Login Page
return view('auth.login');
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
$this->validate($request, [
'email'=> 'required|email',
'password' => 'required',
]);
if (!auth()->attempt($request->only('email', 'password'), $request->remember)) {
return back()->with('status', 'Invalid Login Details' );
}
return redirect()->route('admin.dashboard');
}
I have the roles tables and pivot table set up but not sure how to amend the return redirect()->route('admin.dashboard'); to the correct code so depending if the user is an admin or a standard user it uses the correct route
You can give simple condition after login attempt success like below.
if (auth()->user()->role == 'admin') {
return redirect()->route('admin.dashboard');
}
return redirect()->route('user.dashboard');
As per your described question, you have a different table for assign roles to the user. So you have to create relation with roles table to identifies the role of the user.
You'll need to make sure to import the Auth facade at the top of the class. Next, let's check out the attempt method:
use Illuminate\Support\Facades\Auth;
...
public function store(Request $request) {
// ...
if (!auth()->attempt($request->only('email', 'password'), $request->remember)) {
return back()->with('status', 'Invalid Login Details' );
}
// Redirect to admin dashboard
return redirect()->intended('route.dashboard');
}
For more details read the Docs Manually Authenticating Users

Why is my laravel policy authorization not working after a while

I'm following the laracasts 5.7 series and I was working on the authorization part using policies. It was working fine when I first added it. But the next day when I opened the app again (without TOUCHING any of the code) I kept being thrown to a 403 error. This happened the two times already. At first I just thought I messed up the code. So I redid the whole policy authorization again. But the second time, I made sure everything was working fine before I saved my code. And then the same thing happened.
Here's my code so far:
ProjectPolicy.php:
public function touch(User $user, Project $project)
{
return $project->owner_id == $user->id;
}
AuthServiceProvider.php:
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* #var array
*/
protected $policies = [
// 'App\Model' => 'App\Policies\ModelPolicy',
'App/Project' => 'App\Policies\ProjectPolicy',
];
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
//
}
}
web.php:
Route::resource('projects', 'ProjectsController')->middleware('can:touch,project');
ProjectsController.php:
use App\Project;
use Illuminate\Http\Request;
class ProjectsController extends Controller
{
public function __construct() {
$this->middleware('auth');
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$projects = Project::where('owner_id', auth()->id())->get();
return view('projects.index', ['projects' => $projects]);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('projects.create');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$validated = request()->validate([
'title' => 'required',
'description' => ['required','min:5']
]);
$validated['owner_id'] = auth()->id();
Project::create($validated);
return redirect('/projects');
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show(Project $project)
{
// $this->authorize('update', $project);
// abort_if($project->owner_id !== auth()->id(), 403);
// $this->authorize('touch', $project); // from ProjectPolicy
// abort_if( \Gate::denies('touch', $project), 403);
return view('projects.show', ['project' => $project]);
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit(Project $project)
{
return view('projects.edit', ['project' => $project]);
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Project $project)
{
$project->update(request(['title','description']));
return redirect()->action(
'ProjectsController#show', ['id' => $project->id]
);
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy(Project $project)
{
$project->delete();
return redirect('/projects');
}
}
To be clear: It was working the night before, and the next day when I opened the app it kept throwing me to a 403 error even when I didn't edit the code at all. I don't know what's happening at all.

Laravel 5 authentication weird behaviour

Before explaining the problem. Let me explain, things i have tried out.I ran the command
php artisan make:auth
it created files like HomeController, a directory auth which had register & login pages. in my application i have a directory Pages. i opened up AuthenticatesUsers trait and changed
return view('auth.login'); to my view return view('Pages.login');
After that: i changed view of showRegistrationForm methods view return view('auth.register'); to return view('Pages.register'); from RegistersUsers.php
Here is UserController
lass UserController extends Controller {
//constructor
public function __construct() {
}
//Admin: return view
public function showCommunity() {
$Community = Community::latest()->get();
$Ideas = Idea::latest()->get();
return view('privatePages.communities', compact(array('Community', 'Ideas')));
}
Routes that were generated by php artisan make:auth
Route::auth();
//Auth Controller
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
Now coming back to the problem. yesterday morning. When i opened up localhost/auth/register. Registration process was working fine and data was storing in DB. But there was an issue with login view. Neither it was throwing an error on wrong credentials nor logged the user in on correct credentials. Later in the evening. Login view was working and throwing an error even upon entering correct credentials it said Credentials does not match record. But registration process was not working and data was not storing in DB. It really confusing.
Here is AutheticatesUsers File
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Lang;
//use App\Http\Requests\UserRequest;
trait AuthenticatesUsers
{
use RedirectsUsers;
/**
* Show the application login form.
*
* #return \Illuminate\Http\Response
*/
public function getLogin()
{
return $this->showLoginForm();
}
/**
* Show the application login form.
*
* #return \Illuminate\Http\Response
*/
public function showLoginForm()
{
$view = property_exists($this, 'loginView')
? $this->loginView : 'auth.authenticate';
if (view()->exists($view)) {
return view($view);
}
return view('Pages.login');
}
/**
* Handle a login request to the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function postLogin(Request $request)
{
return $this->login($request);
}
/**
* 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.
$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'))) {
return $this->handleUserWasAuthenticated($request, $throttles);
}
// 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.
if ($throttles && ! $lockedOut) {
$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->loginUsername() => 'required', 'password' => 'required',
]);
}
/**
* Send the response after the user was authenticated.
*
* #param \Illuminate\Http\Request $request
* #param bool $throttles
* #return \Illuminate\Http\Response
*/
protected function handleUserWasAuthenticated(Request $request, $throttles)
{
if ($throttles) {
$this->clearLoginAttempts($request);
}
if (method_exists($this, 'authenticated')) {
return $this->authenticated($request, Auth::guard($this->getGuard())->user());
}
return redirect()->intended($this->redirectPath());
}
/**
* 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->loginUsername(), 'remember'))
->withErrors([
$this->loginUsername() => $this->getFailedLoginMessage(),
]);
}
/**
* Get the failed login message.
*
* #return string
*/
protected function getFailedLoginMessage()
{
return Lang::has('auth.failed')
? Lang::get('auth.failed')
: 'These credentials do not match our records.';
}
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function getCredentials(Request $request)
{
return $request->only($this->loginUsername(), 'password');
}
/**
* Log the user out of the application.
*
* #return \Illuminate\Http\Response
*/
public function getLogout()
{
return $this->logout();
}
/**
* Log the user out of the application.
*
* #return \Illuminate\Http\Response
*/
public function logout()
{
Auth::guard($this->getGuard())->logout();
return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/');
}
/**
* Get the guest middleware for the application.
*/
public function guestMiddleware()
{
$guard = $this->getGuard();
return $guard ? 'guest:'.$guard : 'guest';
}
/**
* Get the login username to be used by the controller.
*
* #return string
*/
public function loginUsername()
{
return property_exists($this, 'username') ? $this->username : 'email';
}
/**
* Determine if the class is using the ThrottlesLogins trait.
*
* #return bool
*/
protected function isUsingThrottlesLoginsTrait()
{
return in_array(
ThrottlesLogins::class, class_uses_recursive(static::class)
);
}
/**
* Get the guard to be used during authentication.
*
* #return string|null
*/
protected function getGuard()
{
return property_exists($this, 'guard') ? $this->guard : null;
}
}
One more thing for registration process. I am not using laravel's Request rather my own created 'UserRequest`. If any other information is needed. i would provide that. Any help would be appreciated.

ErrorException in SessionGuard.php | Getting error when trying to register user while creating new order

I want user to register and also buy a package. To do that I took input for registration details and package details. Now when I'm processing order to save package details in session and register, I get this error : Argument 1 passed to Illuminate\Auth\SessionGuard::login() must be an instance of Illuminate\Contracts\Auth\Authenticatable, instance of Illuminate\View\View given, called in C:\xampp\htdocs\rename\app\Traits\OrderRegister.php on line 63 and defined. I'm using an trait to register user and return back to function when registration is complete.
OrderController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Package;
use App\ListingType;
use Illuminate\Support\Facades\Auth;
use App\Order;
use Carbon\Carbon;
use App\Traits\OrderRegister;
class OrderController extends Controller
{
use OrderRegister;
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index($type)
{
$listingtype = ListingType::where('type', '=', $type)->first();
if ($listingtype) {
$packages = $listingtype->packages()->get();
return view('packages.index', compact('packages'));
}
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create($id)
{
$package = Package::where('id', '=', $id)->first();
if (Auth::check()) {
return view('order.create_loggedin', compact('package'));
}
else {
return view('order.create_register', compact('package'));
}
}
/**
* Process a new order request. Store order values in session.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function process(Request $request)
{
$order = ['package_id' => $request->package_id, 'order_qty' => $request->no_of_listing];
session(['order' => $order]);
if (Auth::guest()) {
return $this->register($request); // need to check session for orders available in OrderRegister trait.
}
return $this->store($request);
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
if($request->session()->has('order')) {
$package = Package::where('id', '=', $request->package_id )->first();
if($request->user() == Auth::user()) {
for( $n=1;$n<=$request->no_of_listing;$n++) {
$order = new Order;
$order->package_id = $request->package_id;
$order->user_id = Auth::user()->id;
$order->expire_at = Carbon::now()->modify('+'.$package->duration_in_months.' months');
$order->save();
}
return redirect('/');
}
}
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
trait : OrderRegister.php
<?php
namespace App\Traits;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Validator;
trait OrderRegister
{
use RedirectsUsers;
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'username' => 'required|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'username' => $data['username'],
'password' => bcrypt($data['password']),
]);
$user->profile()->save(new UserProfile);
return $user;
}
/**
* Execute the job.
*
* #return void
*/
public function register(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
Auth::guard($this->getGuard())->login($this->create($request->all()));
return $this->store($request);
}
/**
* Get the guard to be used during registration.
*
* #return string|null
*/
protected function getGuard()
{
return property_exists($this, 'guard') ? $this->guard : null;
}
}
I could not find any solution for this error so created my own thread for the first time please someone help.
It throws an error because you are trying to login a vue.
in your OrderController.php you are using create method which return a view.
this method will override the create method on your trait.
So you have something like this :
Auth::guard($this->getGuard())->login(/* A view */);
you can at least rename the method on the trait from create to createUser for example.
then you call it from the guard like this :
Auth::guard($this->getGuard())->login($this->createUser($request->all()));

Resources