How can I force Auth Sign In From Controller - laravel

Okay, so I know about middleware hence the "From Controller" specification in the title but basically, the issue I have is this, I have a SaaS app that I'm adding a gifting feature i.e give someone a plan as a gift and so I need to force login on a regular user while allowing either way on one gifting the plan to make it easier. Makes sense? Anyway, for that reason, I cannot use the auth middleware since I have, and want, only 1 checkout page.
So, how can I force login from my Checkout Controller like the way the auth middleware does it on routes?

Since I haven't gotten a suggestion, I'll post the workaround I came up with and the potential solution I simply have no time to study up on at present:
Likely solution:
Use Auth::guard('guard name here') and you can learn more about this here.
My workaround:
I created another route pointing to the same controller function but one is going through middleware('auth') while the other isn't. Practical example below.
Route::get('checkout/summary', [CheckoutController::class, 'summary'])->middleware('auth')->name('summary');
Route::get('checkout/gift-a-sub', [CheckoutController::class, 'summary'])->name('gift-a-sub');
With this, I only require one page to prevent complications while forcing authentication for regular users while those just opting to gift a plan aren't required to do so and all I have to do then is save the data based on a flag created at the Pricing page.

Related

Do I need to protect Laravel ::post routes from any kind of post besides my own form

If I have two routes:
Route::get('/setup', 'SetupController#index')
Route::post('/setup' 'SetupController#store')
In the SetupController#index I do some checks, for example I check if the user is authentificated. But there are some more rules there that I check.
Should I perform the same checks on the post route too?
Is there any way someone could hit that post route without hitting the get route first? (for example posting in url http://domain/setup?password=1234)
So I guess what I am asking is :
Do I need to wrap the two routes in a middleware and do checks on each of them or is enough to check on the get route?
yes you need to wrap both routes in the middleware.
someone can open anypage (login for example) and edit the html to make a form that point to /setup and put whatever he wants in it.
sure, that someone need to know the architecture of the form to do this, but it's a risk nonetheless.
Normally, you need to add corresponding middlewares for different urls, for the get route, you can use ReplayAttackMiddleware for unnecessary attacks; and for the post route, I think you need to add different roles for different users, and JWT is a really good tool for authentication.

Creating Dynamic Custom Validator in Laravel

Before you read the title and vote as duplicate, hear me out. I haven't been able to find another example of what I am after.
I have a Laravel 5.5 application that uses the built in Laravel Auth class for user management.
If a user tries to perform an action I want to stop/allow the action based on the user's level.
I have gone through the docs and found that I can write my own custom validation rules by implementing the \Illuminate\Contracts\Validation\Rule interface and call it in the controller but I want to, basically, pass the validator the user level and the level required and validate from that.
Can someone please point me in the right direction to do so?
I dont think the form validation is the best way to make what you want. If you want to restrict actions depending on user permission (here level), you have to create the levels and then check for it before try to validate the form.
I recommend you tu use the Authorization part of Laravel which is well explained in the doc

Permissions in Laravel - ACL vs Middleware

I'm having a bit of trouble understanding the proper times to use ACL or middleware in Laravel. I do understand the examples on their site and Laracasts, but they're rather simple examples.
This isn't anymore complicated by any means, but I didn't see examples for these. Let's say I have two routes that allow a user to create a task. The first being the GET request to fill out the information, and the second being the POST to store the information. There are some users that are not allowed to create tasks based on their role. In both cases, there isn't a particular object that exists, which is what the ACL requires as far as I understand. So would I use middleware for something like that? And when an object exists, use ACL for that?
An alternative I've been trying to fit in is the use of Form Requests too, but then I'd have to create a Form Request object for each route (although I don't really mind personally).
What is a good approach to limiting acccess to actions, when there isn't a specific action to act upon?
Thanks in advance.
Notice: I was going to post this as a comment, but it got a little too extent. Feel free to wait for better answers and maybe consider this just a comment.
I think that you're missing the whole point here. You can have a middleware that consults the ACL or you can use the FormRequest to consult the ACL or use each of them separately. For instance, at the authorize method of the CreateTaskRequest, you can check the ACL to see if the user has the proper role to create a task.
You might be getting too hooked up when Jeff tries to check if the user owns the post. That kind of ACL is record-oriented, but you can have a role that just takes the user as a parameter (and no other entity) and see if that user just has a specific role. By returning true, the action is authorized, otherwise it's denied.
A middleware have more to do with the route instead of the request. You can also have a middleware that gets the authenticated user and check if it has the role to create a task. Those are different ways to achieve the same thing (which is one of the benefits of Laravel, having lots of ways to achieve the same goal).
Your specific action to act upon is the "Create new Task" action. Who do you want to be able to do that? Users that have the role manager? Users that have the permission create-task?
At the end of the day, what I would consider is:
Are there lots of routes that will have the same rule? Maybe a middleware would be a good choice.
Are there specific rules for each kind of operation? Can an user that did not create a task be able to edit one? Form Requests might be easier to achieve this kind of specification
Which $this environment would make my life easier? $this from the Form Request or $this from a middleware?
One thing I learned from Jeff's class are that he teaches too much cool stuff and sometimes I end up missing one point or two. Try re-watching the basic steps again and maybe stop when you think you found something that would work. Then implement that and see what your case differs from his and how you think he'd write that feature.

How to protect a controller in a Spree extention so that only the admin of the shop can access it?

I am trying to develop a Quote Extention for Spree, allowing customers to upload files to AWS S3.
I would like to "secure" via authentication some of its actions and Spree provides useful helpers to that end, however I couldn't manage to get it to work.
As far as I understood the matter, I have to add this line in the QuotesController.
include Spree::Core::ControllerHelpers::Auth
in my controller, as shown in this gist
Unfortunately, I still get the undefined method error authenticate_user!
For the sake of keeping this thread DRY, you can find more on my question on Spree's repository issue #5794
Any contribution is very welcome.
Thank you.
So I could delete the question since it was based upon wrong assumptions, but I rather detail how I managed to solve the authentication of the QuotesController.
Many thanks to #Hates_ and all the people in the Spree IRC for their answers!
The first wrong assumption was in regard to the design of the QuotesController which should be split up in 2 parts one for the customers, one for the shop admin backend. The second wrong assumption was that the include Spree::Core::ControllerHelpers::Auth was not going to give me the protection I wanted. So here is what I ended up with:
The Admin Side
In Spree, in order to have your controller enjoy the "protection" of the admin of the shop, this controller has to inherit like that Spree::Admin::QuotesController < Spree::Admin::BaseController. This controller would live in app/controllers/spree/admin/quotes_controller.rb. This is all you need to "protect" it. Also, it will make your views integrate into the shop's backend nicely.
The Customer Side
It is better, by design, to make another QuotesController using a different namespace app/controllers/spree/quotes_controller.rb and inheriting like that:
Spree::QuotesController < Spree:Core::BaseController

How to achieve clickstream or click tracker function in Django?

I have a question that i want to add the function to track the click stream of user in my website, How can I achieve this, using ajax tracker or Django-tracker modules?
I have actually wrote a django-clickstream application, I just haven't open sourced it yet, I want to test it out to make sure it works well before releasing it.
Here are the steps you need to do to reproduce what I did, it isn't too hard.
First off you would need to keep track of each visitor for the life of their session or cookie. You can do this using django-visitor or roll your own.
Once you have a visitor you can create a custom middleware that will look at each request and then log what url each visitor visits to a database table. Then all you need to do is create a simple web page where you can view the different click streams by visitor.
One important thing to note is that you will need to setup an exclude filter so that the middleware doesn't pick up any urls that you don't want to track (static, etc), I did this with a simple list of regular expressions that I stored in the settings file. If the url doesn't match one of the regular expressions then log it.
The table will get pretty big real fast if you have a popular website so you will need to create a management command to clean out the old records from your tables.
Django-visitor: https://bitbucket.org/kencochrane/django-visitor
Edit:
Check out Django-clickstream: https://bitbucket.org/kencochrane/django-clickstream

Resources