I need some advice, basically I have an application where users can register as normal customers, and inside the dashboard there is a option to register as an author for a list of categories. A customer can be many authors.
So basically after registering/subscribing as an author in the custom dashboard appears a box of his author(s) that he created and after clicking it goes to a specific dashboard with different menu, etc.
My only issue is when I start to create the permissions, for example I created a Middle-ware with the name of "author", so when someone try to access these pages it must be an author.
Middleware code:
public function handle($request, Closure $next)
{
if(isset($request->id) && auth()->check() && count(auth()->user()->authorsProfile) > 0){
return $next($request);
}
return redirect('/dashboard')->with("error","Only Authors Allowed");
}
example:
Route::group(['middleware' => ['auth','author']], function() {
//Dashboard
Route::get('authorsarea/{id}','AuthorController#dashboard')->name('author-dashboard');
});
So the second validation i need to make is inside the controllers, I need to check based on the ID if this an author id belongs to the customer/user.
example:
public function dashboard($id)
{
$user = Auth::user();
$user_author = Author::find($id);
if($user_author->user_id != Auth::user()->id){
return back()->with("error","This Author is not you");
}
//Go to dashboard
return view('frontend.author.dashboard');
}
I feel that pasting alwasy this code and checking if this author belongs to the user doesnt feel quite clean, is there a better way than pasting always this code in each page controller where I try to access a private area for authors?
Or even if you guys feel that there is a completely different way of doing all of this I'm open to it.
You can make another middleware and have the check there, similar to the author middleware you have created. Something like this:
public function handle($request, Closure $next)
{
$authorID = $request->route()->parameter('id');
$user_author = Author::find($authorID);
if($user_author->user_id != auth()->user()->id){
return back()->with('error', 'This Author is not you');
}
return $next($request);
}
Related
Please forgive me if my question is too generic but I am at my wits end.
I have a users table with a level field as shown given below:
$table->unsignedSmallInteger('level')->after('password');
I want to redirect the user to different dashboards based on the value of the level field. For example for level 0 user
\admin\dashboard
for level 1 user
\user\dashboard
I am using Laravel 8.4 and laravel/breeze for authentication.
Thank You
Ok, found a solution.
On routes\web.php I have commented out the default dashboard route and created a new route for /dashboard and pointed it to App\Http\Controllers\DashboardsController#index
// Route::get('/dashboard', function () {
// return view('dashboard');
// })->middleware(['auth'])->name('dashboard');
require __DIR__.'/auth.php';
Route::get('/dashboard','App\Http\Controllers\DashboardsController#index')->middleware(['auth'])->name('dashboard');
index function of DashboardsController
public function index() {
$data['authenticated_user'] = Auth::user();
if($data['authenticated_user']->level == 0) {
echo "Admin";
} elseif($data['authenticated_user']->level == 1) {
echo "Employee";
} else {
echo "Security";
}
}
Basically this will accomplish what I want to achieve.
Thanks
I am using Laravel framework. There is a function in controller that creates session with name store_id
StoreController.php
function initiate($id)
{
//Some queries
session['store_id' => 'some value'];
}
Now if I run this function on one tab then session::get('store_id') is going on. But if I open another tab in the same browser then again run the function that means session('store_id') will be again set. How do I handle this situation that if there is already a session then it should redirect to it's perspective url.
Okay first of all, Bruuuhhhh been there and done that
Alright, lets begin. you want that if there is already a session with store_id going on then you want user to redirect or send back.
In your controller add this
public function initiate()
{
if(session()->has('store_id'))
{
//What ever your logic
}
else
{
redirect()->to('/store')->withErrors(['check' => "You have session activated for here!."]);
}
}
Most probably you would be wondering that user can just go to other url after /store/other-urls Yess he can.
To avoid this. Add a custom middleware
php artisan make:middleware SessionOfStore //You can name it anything.
In that middleware
public function handle($request, Closure $next)
{
if($request->session()->has('store_id'))
{
return $next($request);
}
else
{
return redirect()->back()->withErrors(['privilege_check' => "You are not privileged to go there!."]);
}
return '/home';
}
in your main store page. Add an anchor tag Stop Service
Now in your web.php
Route::group(['middleware' => 'SessionOfStore'], function()
{
//Add your routes here.
Route::get('/stop', 'StoreController#flushSession');
});
Now you have restrict access to urls and has checked the sessions.
Now in
public function flushSession()
{
//empty out the session and
return redirect()->to('/home');
}
The Laravel session helper has the function has to check this.
if (session()->has('store_id'))
{
// Redirect to the store
}
else
{
// Set the store id
}
The documentation contains all of the possible functions that can be used with the session helper.
I am currently developing a website using Laravel.
A user belongs to 1 and only 1 group.
How do I restrict the route
Route::('/view/profile/{id}', 'ProfileController#showProfile');
to be only accessible by other users belonging to the same group. I would also like to allow the admin to access this route. However the admin does not belong to any group.
I know there are two ways to solve your problem.
You can create a custom middleware and bind it to your route.
Or you can do a simple check in your controller method.
I will give an example of the second method since it is the easiest.
Example:
// YourController.php
public function yourMethod()
{
// Get the user from authentication
$user = Auth::user();
// Check user and redirect to login when NULL
// This also can be done with auth middleware (check link in method 1)
if (!$user) return Response::redirect('yourLoginRoute');
// Check if has not group throw forbidden
if ($user->group->id != theGroupId) return App::abort(403);
}
Edit after comment #PaulLucero
So if I understand correctly only users of the same group can visit eachothers profile page (view/profile/{id}). Also you want to use a middleware to solve this problem but are unable to retrieve the route parameter {id}.
You can retrieve a parameter in Laravel 4 outside a route by using Route::input('yourParameter'). Check this and scroll down to Accessing A Route Parameter Value.
Example:
class YourMiddleware
{
public function handle($request, Closure $next)
{
// Get id from route and get user model
$user_id = Route::input('id');
$user = User::find($user_id);
// Do some checks
....
// Get user from auth
$auth_user = Auth::user();
// Do some checks
....
// If groups don't match throw 403
if ($user->group_id != $auth_user->group_id) return App::abort(403);
return $next($request);
}
}
I think this should do the trick.
create a custom middleware try like this
public function yourMethod()
{
$user = Auth::user();
if ($user->group_id == 1) {
return Response::redirect('yourRouteToGroupID-1');
else if(if ($user->group_id == 2) {)
return Response::redirect('yourRouteToGroupID-2');
else{
return App::abort(403);
}
}
I am using the Laravel 5 built in user stuff with Entrust for user roles and permissions. I have two roles set up which are administrators and users. Basically what I want to do is have two different forgotten password email templates - one for users and one for administrators. So when a user enters their email address to get the reset link emailed to them I need to check what sort of user they are first and then send them the right template. I don't want to have to do any sort of hacky stuff in the standard email template their must be a way to do this in the controller or something surely? Anyone know how I would do it?
You can probably prompt them to enter their email and when they submit you can grab it in the controller:
public function forgot()
{
$email = Input::get('email');
$user = User::where('email', $email)->first();
if($user->type == 'admin') {
// logic to email admin with admin template
} else {
// logic to email user with user template
}
// redirect to success page letting user know the email was sent
return View::make('someview');
}
Or better yet, just pass the user type to an email service that handles the emailing:
public function forgot()
{
$email = Input::get('email');
$user = User::where('email', $email)->first();
$emailService->sendForgotForType($user->type);
// redirect to success page letting user know the email was sent
return View::make('someview');
}
If you are using Laravel 5's built in User Management:
To override the default template used you would need to manually set the $emailView in the PasswordBroker.php by writing a new class that extends PasswordBroker.
For example, comment out 'Illuminate\Auth\Passwords\PasswordResetServiceProvider' in config/app.php
Then create an extension class:
use Illuminate\Contracts\Auth\PasswordBroker;
use Illuminate\Contracts\Auth\CanResetPassword;
class MyPasswordBroker extends PasswordBroker {
// override
public function emailResetLink(CanResetPasswordContract $user, $token, Closure $callback = null)
{
// Override Logic to email reset link function perhaps using the example above?
}
}
Then you would need to bind your new MyPasswordBroker class to AppServiceProvider at app/Providers/AppServiceProvider.php in the register method (below found online):
$this->app->bind('App\Model\PasswordBroker', function($app) {
$key = $app['config']['app.key'];
$userToken = new \App\Model\NewUserToken;
$tokens = new \App\Repository\NewTokenRepository($key,$userToken);
$user = new \App\Model\NewUser;
$view = $app['config']['auth.password.email'];
return new \App\Model\PasswordBroker($tokens, $users, $app['mailer'], $view);
});
Definitely moderately advanced stuff, if you can handle it - great. Otherwise I would possibly look into using an authentication package with built in features you need.
I am making a system using CakePHP in which the users can be either A, B or C. Like student, teacher and some other role. Is it possible to let them all login via 1 link? so not /students/login and /teachers/login, but something like www.somewebsite/login for all of them?
Read this tutorial, it exactly covers what you're asking for. Also read this section.
It does not make any sense at all to have different controllers for different types of users, you'll just duplicate code. If you need to take different actions based on the role you can do that within your login method by calling another method like afterStudentLogin() from within your login() method and do role specific things there. The reason for that is that a single method should always just do one task, so you decouple the role specific code from it in a separate method.
public function login() {
if ($this->Auth->user()) {
/* ... */
$callback = 'after' . $this->Auth->user('role') . 'Login');
$this->{$callback}($this->Auth->user());
/* ... */
}
}
Even if the user types are very different, they all will share a common thing: The login. In this case have an users table and for example student_profils table and teacher_profiles table. If the difference is just a few fields I would put them all in one table like profiles.
If you want to have /login instead of /users/login you should use routing.
Router::connect(
'/login',
array(
'controller' => 'users',
'action' => 'login'
)
);
You can also take a look at this Users plugin which covers a lot of the usual user related tasks. And here is a simple multi-role authorization adapter.
A simple basic login function depending on user group would look like as given below
<?php
public function login() {
//if user already logged in call routing function...
if($this->Session->read('Auth.User')) {
$this->routing();
}
if ($this->request->is('post')) {
if ($this->Auth->login()) {
//if user status is active...
if ($this->Auth->user('status') == 1){
//redirect users based on his group id...
if($this->Auth->User('group_id')==1){
$this->redirect($this->Auth->redirect('/admins/dashboard'));
}
else if($this->Auth->User('group_id')==2){
$this->redirect($this->Auth->redirect('/teachers/dashboard'));
}
else if($this->Auth->User('group_id')==3){
$this->redirect($this->Auth->redirect('/students/dashboard'));
}
}
else{
$this->Session->delete('User');
$this->Session->destroy();
$this->Session->setFlash('Your account is not yet activated. Please activate your account to login.', 'warning');
}
}
else {
$this->Session->setFlash('Your username or password was incorrect.', 'error');
}
}
}
//just route the loggedin users to his proper channel...
public function routing() {
if($this->Session->read('Auth.User.Group.id') == 1) {
$this->redirect('/admins/dashboard');
}
else if($this->Session->read('Auth.User.Group.id') == 2) {
$this->redirect('/teachers/dashboard');
}
else if($this->Session->read('Auth.User.Group.id') == 3) {
$this->redirect('/students/dashboard');
}
else {
$this->Session->destroy();
$this->redirect('/');
}
}
?>