This episode is for members only

Sign up to access "Build a Livewire CSV Importer/Exporter" right now.

Get started
Already a member? Sign in to continue
Playing
13. Securely downloading exports

Transcript

00:00
This is where things start to potentially get dangerous because we are storing a bunch of data on our local file system over here, which can be downloaded by a user.
00:10
So we want to safeguard this information to make sure no one can download it unless they own these files. So we already have a record, an export record in here that references the file name and the user ID. So we have the ability to authorise this, which is really important. Let's go through the process of creating out the link to download this, and then we will go ahead and look at making sure we authorise this.
00:38
So we're going to add in another web route here for the download of this, and I think we'll create out a controller for this. We haven't for the other files because they're just rough outputs, but let's make out a controller here called export controller. OK, so under our export controller, let's just make this invocable. It's just going to have one job. And what do we need to accept into it? Well, we need to accept in a specific export.
01:07
That could be by its ID. It could be by anything. So we'll just do it by its ID for now. OK, we'll just leave that for now. We won't do anything in there. Let's just get this route built out so we can at least link through to it. So this is just going to be a get route through to exports and it will be the export itself and it will be the download. So we're not going to make this time restricted just yet, but we will do a little bit later and we will sign the URL, the download URL.
01:33
So even if the link is accidentally given out, it will expire at some point, but we'll keep this simple for now. So let's reference our export controller here. And actually, what should we do? Shall we? Let's make this download. So let's not make this invocable. Call this download just so it's a little bit clearer. OK, so the name for this.
01:55
Is going to be exports.download and we pretty much just want to take the same middleware here because we need to be authenticated and potentially verified to access this. OK, so we've got exports.download and we know that an export needs to be passed into here. So what we can do is over in our export table, we can generate the route for this now. So let's say route exports download and we'll just directly pass the export into there and that should now link through to the correct place.
02:26
Great. So that's working. OK, so the next step is actually downloading the file. This is incredibly easy to do. All we use is storage. So we use the storage facade. We use the download method and we're on the export. We grab the file. So this by default is going to be using the local file system. Let's just look at this.
02:49
So in our case, it's just a full path that we're passing in and that will download from this private folder here that will deliver that to the user and they will receive the file. We're not authorizing yet. We will do that in just a second. I just want to make sure that when I click on this, it downloads the file correctly. And yeah, sure enough, it does. I can open this up in numbers and you can see we've got all of the transaction data in there. So that is working nicely. But anyone can pass in any ID here. So we want to make sure this is authorized.
03:20
A couple of ways that we could do that. We could do that either down here directly in the controller. I always like to lean on form requests, even if I'm not validating any data. So I'm going to create out a form request here just to keep things nice and tidy. So let's create out an export download request and we are going to say export download request request.
03:44
And if we head over to this export download request, of course, we don't have any validation rules here because it's a GET request. But for authorize, we can basically just make sure that this user owns this particular export. How do we do that? Well, again, we are going to create our policy. Now it might seem mad that we're creating out all these loads of classes to do stuff,
04:06
but this just helps keep things really neat and tidy as our application grows. So we're again going to come over and we're going to generate a policy. So let's create our policy here called export policy specifically for this model. This export policy will contain a bunch of rules.
04:23
So basically, we can either say, can we see this or show this? Can we download this? So we will implicitly get the user passed into here. And we'll get the export that we will pass in. Now, what's the condition under this policy for this model that the user can download and export?
04:46
Well, it's that the user ID matches the export user ID. That means that they own it. So now in the authorize method, we can say auth user can, we can use the name of that method that we've just created in the policy. This will be automatically registered for us. We don't need to register it.
05:05
And we can pass in the export here, which this is the model that's going to get passed through to the policy here. This will return either true or false, and it will either deny it or allow it and download the file. So we're not writing any tests here, but we can manually test this in a second. I'm going to click download and you can see that that works because I own this.
05:26
But over in the database, how about we create out a test user and assign one of my exports to this user and try and download it. So let's say mabel.cocos.com. Let's go over to our exports and I'm going to assign this user 2. I'm going to keep this here and click download and you can see this action is done authorized. So I've switched that over in the back end to another user. And of course, now I've refreshed, it's gone.
05:51
OK, let's switch that back over to user ID 1. And there we go. We now have the ability to securely, which is the most important part about this, download our exports. Later, we will refactor this to create signed URLs that expire after a certain amount of time. But for now, this is pretty good.
22 episodes2 hrs 18 mins

Overview

Let's build a powerful CSV importer and exporter with Livewire, completely from scratch.

This can handle millions of rows, be reused for multiple models, and by using queues, doesn't require the browser to be open.

This course is for you if:

  • You need a robust drop-in importer and exporter component for your models that you have full control over
  • You want to brush up on some advanced Livewire concepts
  • You want to learn about queues in Laravel
Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!

Episode discussion

No comments, yet. Be the first!