I need to restrict the access to some parts of the application depending on the user logged in. I mean for example to let a user edit only its own posts on a blog application.
Is there a better approach than in every function of the controller, if the user is not the owner of the required post, redirect to some error page?
For example if my routes are /post/{post_id}/edit, /post/{post_id}/preview, /post/{post_id}/delete, can I somehow declare a general function in the PostController like:
if(Post::find($post_id)->user_id != Auth::user()->id){
return View::make('access-error');
}
Thanks!
In your controller you can do something like this:
public $check = ['edit', 'preview', 'delete'];
public function callAction($method, $parameters) {
if(in_array($method, $this->check, true) &&
$post_id = $parameters['post_id'] &&
Post::find($post_id)->user_id != Auth::user()->id) {
return View::make('access-error');
}
return parent::callAction($method, $parameters);
}
You could throw a 401 error and catch it elsewhere to display a custom page
App::abort(401);
http://laravel.com/docs/4.2/errors#handling-404-errors
Related
I actually am not able to understand why I am getting the following error.
App\Models\User::team must return a relationship instance, but "null" was returned. Was the "return" keyword used?
I am basically creating test cases for simple orders for ecommerce.
User Modal
public function team(): BelongsTo|null
{
if (!empty($this->team_id)) {
return $this->belongsTo(Team::class);
}
return null;
}
Test case
public function test_order_status_update()
{
$order = $this->create_order($this->books->id, $this->appUser->id, $this->address->id);
$response = $this->actingAs($this->user)->put('orders/' . $order->json('order.id'), [
'order_status' => 'ordered',
]);
$response->assertRedirect('orders/' . $order->json('order.id'))->assertSessionHas('success');
}
In addition, I have another feature in my application called pages access control, which controls page access for multiple users (admin, developer, and users).
I have implemented this feature manually using middleware.
Middlware.php
public function handle(Request $request, Closure $next)
{
//teams 1-Developer 2-Admin 3-Management 4-Marketing 5-Audit 6-Sales 7-Bookstores 8-Delivery 9-User
$team = $request->user()->team;
if ($team->id == 1 || $team->id == 2) {
return $next($request);
}
$pages = auth()->user()->pages->merge(auth()->user()->team->pages);
$currentRouteName = $request->route()->getName();
$pages->contains('route_name', $currentRouteName) ?: abort(403);
return $next($request);
}
Based on the error above, I believe the actingAs function is unable to obtain authenticated user information, which is why my test failed.
How can I fix this?
Simply don't check your team_id:
public function team(): BelongsTo
{
return $this->belongsTo(Team::class);
}
Laravel tries to be smart. If team_id isn't set, it will just return null. However, if you don't return the BelongsTo, the magic code of Laravel will trip when you try to access user->team
So for example we have url:
localhost://menu/men/shoes/nike
So when user types this url in browser i want to redirect him to page localhost://menu/SOMETHINGELSE/shoes/nike
localhost://menu/men/clothes/addidas => localhost://menu/SOMETHINGELSE/clothes/addidas
How can i do this in Laravel?
Add redirect in your web.php route file.
Route::redirect('/menu/men/shoes/nike', '/menu/SOMETHINGELSE/shoes/nike');
Else you have to handle on a controller basis, imagining something like a CategoryController.php.
class CategoryController {
public function view(Category $category) {
if ($category->slug === 'nike') {
return redirect('menu/SOMETHINGELSE/shoes/nike');
}
...
}
}
I'm encountering a problem where a redirect from one route to another is calling the targeted controller method twice. This question addresses a similar issue, but the OP passing a 301 status code was deemed to be the issue in the accepted answer, and I'm not specifying any status code. I'm also using the session state for parameters. The relevant code looks something like this:
public function origin(Request $request) {
// Assume I have set variables $user and $cvId
return redirect()
->action('SampleController#confirmUser')
->with([
'cvId' => $cvId,
'userId' => $user->id,
]);
}
public function confirmUser(Request $request) {
$cvId = session()->get('cvId');
$userId = session()->get('userId');
if (is_null($cvId) || is_null($userId)) {
// This is reached on the second time this is called, as
// the session variables aren't set the second time
return redirect('/home');
}
// We only see the view for fractions of a second before we are redirected home
return view('sample.confirmUser', compact('user', 'cvId'));
}
Any ideas what could be causing this? I don't have any next middleware or any of the other possible causes that are suggested in related questions where controllers are executed twice.
Thanks for any help!
Have you tried passing values in parameters? Try the below code.
public function origin(Request $request) {
// Assume I have set variables $user and $cvId
return redirect()->action(
'SampleController#confirmUser', ['cvId' => $cvId, 'userId'=>$user->id]
);
}
public function confirmUser(Request $request) {
$cvId = $request->cvId;
$userId = $request->userId;
if (is_null($cvId) || is_null($userId)) {
// This is reached on the second time this is called, as
// the session variables aren't set the second time
return redirect('/home');
}
// We only see the view for fractions of a second before we are redirected home
return view('sample.confirmUser', compact('user', 'cvId'));
}
So i have a variable in my routes.php and i want to pass it to the route::get, this is my code for more details :
$user = User::find(Auth::user()->username);
Route::get('/services/here i want to put my variable', 'ServiceController#show');
so please if someone has any idea i will be very appreciative
The problem with variating your routes with something like:
$user = User::find(Auth::user()->username);
Route::get("/services/$user->username", 'ServiceController#show');
Is that you may enconter some problems in cases where the user does't exists. If you do that and go to your command line and execute:
php artisan routes
There will be no logged user so that route will be pointed to /services/. What you have to do to prevent those cases is to create a filter and process your route on it:
The route:
Route::get("/services/{username}", array('before' => 'user-must-be-logged-in', 'uses' => 'ServiceController#show'));
A filter to do some checks on it:
Route::filter('user-must-be-logged-in', function()
{
if ( ! Auth::check())
{
App::abort(404); /// user is not logged in, this route does not exist
}
if ( ! User::where('username', $username)->first() )
{
App::abort(404); /// user does not exists, this route does not exist
}
if (User::where('username', $username)->first()->id !== Auth::user()->id)
{
App::abort(404); /// selected is not the current logged user, this route does not exist
}
});
A controller doing whatever you need with it:
class ServiceController extends Controller {
public function show()
{
$user = User::where('username', $username)->first();
// now do whatever you need with your user;
}
}
assuming its $user you want to put in there
$user = User::find(Auth::user()->username);
Route::get("/services/$user", 'ServiceController#show');
swap single quotes for doubles and pass in your var (either that or drop out of your single quotes concat in with . your var
What I basically want is user permissions.
I've got an table called 'accounts' in my database. There is a column called 'group_id'.
I want to set it when the 'group_id' = 3, then the user is admin. Then he can view special sites, buttons, and things like that. I've tried to implement something like that:
public function ($roleName) {
$role = $this->roles;
if ($role->name == $roleName) {
return true;
}
return false;
}
Also, I don't know what and how the model is needed, do I need an new one and things like that.
Old post, but maybe someone will find this useful
Add a method to your User model that returns true if the user is an admin. In our case here, it's simply "is our group_id equal to 3?"
// models/User.php
class User extends Eloquent
{
...
public function isAdmin()
{
return $this->group_id == 3;
}
}
Next add a filter that can be used to protect routes
// filters.php
Route::filter('admin', function($route, $request)
{
if ( ! Auth::user()->isAdmin())
{
return App::abort(401, 'You are not authorized.');
}
});
Finally use the filter to protect a group of routes. I this simplified case, only an admin user could access /admin
// routes.php
Route::group(array('before' => array('auth|admin')), function()
{
Route::get('/admin', function()
{
return Response::make("You're an admin!");
}
});
Based on this post:
http://laravelsnippets.com/snippets/admin-route-filter
I suggest Authority for Laravel 4
I personally use Verify package for user management.