Transcript from the "Reviewing the App Code" Lesson
>> At this point, we have built a full fledged app, right? So we started by loading data that was hard coded. We were pulling up .netlify/functions/boop, and that just brings up this text that we were echoing back, righ? The simplest possible thing that we could write as a serverless function is this.
[00:00:26] This is our reduced use case, the simplest thing you can do. And from there we expanded to have movies loaded from a static file from this JSON. And we took that a step further, we combined our movies with API data from the OMDb so that we could extend it and add scores and ratings and that's how we got to here where we have our scores and ratings being loaded.
[00:00:55] Then we wanted to go a little bit further than that. So we stepped across, and we moved into a database. So we got into Hiroku. And now when we're in Hasura, and Hasura is allowing us to manage our full database and we do that through GraphQL, and the GraphQL is managed with serverless functions.
[00:01:17] So we have this helper that sends off requests to Hasura for us using secure tokens. And we know these are secure because serverless functions don't allow anyone to see the source code which means that we can safely use secure access tokens when making calls and serverless functions. And people can't snoop on that, right?
[00:01:36] They have to do a lot more work to get at this secure data than with a client, if you put it in client side code, you're giving it away, right? So you can't do that. So this allows us to protect those secret keys. Now that we're able to retrieve data, we're loading all of our movies from Hasura, right?
[00:01:54] So we're doing all this to load from Hasura, and then we still augment with the om OMDb API. So we're merging two separate data sources into one response object, right? We combine that whole thing, so that we end up with our movies combined with the response data from the OMDb.
[00:02:14] And that means that we are now looking at a really flexible and extensible way to get at data. And we take that a step further, and we set it up so that we can create movies using a serverless function. We're now creating data, we've created an actual CMS here.
[00:02:32] And by extending that to include user management where we're checking for a roll on a JSON web token. Now we've got a secure CMS, only authorized users are able to make changes to our database. And I want to point out something else that's really cool about this. If you were to do this in other systems, what you've done is if you're talking directly to your database like you would be if you were to just send requests direct to Hasura.
[00:03:01] You're telling somebody where that data is, right? So they would be able to know that our Hasura instance is up at this app here. When you use a serverless function, no one even knows where your data came from. You´re hiding a serverless function, and there´s no indication that data came from this server, or that service, or this SaaS platform, or a JSON file, right?
[00:03:29] And that means you're controlling access, the only thing that you can do on the Hasura database is what we've explicitly defined in our server less functions. There's no other way to really get to it, right? You can't figure out what it is and try to brute force your way in or hammer it with different requests.
[00:03:49] You just get to say, all right, you get to create movies, you get to read movies and create movies. Those are your only two options. There's no edit, there's no delete. For me to delete a movie right now, I have to log into Hasura which is authenticated through the Cicero Cloud, which is tied to my OAuth through Google.
[00:04:08] So, without having to do a whole lot of extra ops background, extra ops work to lock things down. I've sufficiently hidden the implementation details and abstracted those away with serverless functions, that I can feel reasonably confident that my users and their data are not at risk when they go to access this code.
[00:04:31] Now, I'm not a security expert, I'm not gonna pretend to be one. So I do think that you would want to check any production code with a security expert to make sure that you don't get yourself in trouble. But if you're just trying to ship a proof of concept, I believe this is good enough and I believe that this would get you to the point that you could safely open up an app like this to users and start playing with it.
[00:04:54] Start having people you know create some mods, let them create movies, have your database.
>> When you're adding a movie, you can see the data going on the Network tab, right?
>> But it's secure because only a logged in user will be able to see that.
>> Right, only a logged in user would be able to see it. And because we're gonna be using HTTPS, if you look here, we can see that we're automatically getting a SSL certificate. That means that that transaction is encrypted, the token that you're sending, that's secured between you and the endpoint that you're reaching to.
[00:05:37] So you wouldn't want to do this if you didn't have an SSL certificate setup.
>> Is it easy to implement password reset by identity?
>> Yes, so let's go into this thing here. And let's go to our admin page and then I'm gonna log out. There's a recovery set in already.
[00:06:03] So with this, that's already kind of implemented. That'll also be implemented with other services like Auth0 as well, if you wanna use those. And they do have really good docs, if you don't wanna use Netlify Identity, there are lots and lots of options. I'm using Netlify Identity because we're using Netlify Dev for the local testing of everything.
[00:06:24] Everything is kind of built to work together. So it makes it faster for us. I really like it as a solution and it's what I use, but it's by no means the only solution.
>> Seems like a common debugging issue with the workshop is if somebody has run the dev command and then they didn't know it was still running or something, it didn't get shut down properly.
[00:06:50] How do you clear up that port?
>> If at any point you are running the dev command and it's not working, there are a lot of ways that you can do it. But the way that I like to do it, which is pretty brute force is I run killall node.
[00:07:06] And if we go back over here, we'll see that it is no longer running. And so that is a very surefire way to make sure that you're no longer running any node services. If you're using Netlify Dev with a non node process, if you were running a Hugo site or something, that wouldn't work, in which case you would then wanna look at.
[00:07:30] There's another way that you can do it. Let's run netlify dev, and it's gonna run on localhost:8888. So I can go over to this and there's a command that I can run which is lsof -i, and then you put in the port number with a colon in front of it.
[00:07:50] And that'll show you the process that's running that port. So then you could do, kill and the ID, and that stops it. And so then it's stopped over here. So those are two ways, if you know the port number, you can run that lsof command, and I'll bring that back up so you can see it.
[00:08:11] It's here. That's a good one if you know the port, if you don't know the port, but you know what was running it, if it was node, you can run kill all node.
>> Was the authentication token stored in local storage or session storage?
>> Yes, it is stored in the application tab.
[00:08:29] You can find it in local storage and, Let me actually login so we can see it. We have a go true user, and so that go true user is gonna include an access token. So you can grab that, I don't think there's anything in session storage. We do have the the cookie though.
[00:08:59] So if you wanted to do like role based access control, there's a cookie in there as well, where you could check that and make sure that somebody has a role before allowing them to even load a page. There are ways to do that, that I'm not gonna go into cuz there's a very netlify specific way that I don't want to turn this into a straight netlify marketing workshop.
[00:09:23] And then there are ways that you can do it that are more implemented at the nginx or Apache or whatever routing layer that I don't know enough about to show quickly.