WEBVTT

00:00:00.000 --> 00:00:07.000
<v Joel>Welcome to No Compromises. A peek into the mind of two old web devs who have seen some things. This is Joel.

00:00:08.000 --> 00:00:09.000
<v Aaron>And this is Aaron.

00:00:16.000 --> 00:00:24.000
<v Joel>I always beat the drum, like in tips and different things, about making sure your local development matches production.

00:00:25.000 --> 00:00:34.000
This is something... I feel strongly about it because I feel like I've bumped into maybe dozens of ways that it has bit me when they're not the same.

00:00:35.000 --> 00:00:43.000
And I'm talking like, even the patch version of PHP being different, file system, case sensitivity, you name it. I've been there.

00:00:44.000 --> 00:00:46.000
So, Aaron, I know you feel the same way.

00:00:47.000 --> 00:00:53.000
<v Aaron>I would say that before we kind of locked down, having everything be the same in all the different environments.

00:00:54.000 --> 00:00:59.000
I would say before we made that decision, I remember running into scenarios like you just mentioned, at least one time a year, if not longer.

00:01:00.000 --> 00:01:01.000
<v Joel>Right, yeah.

00:01:02.000 --> 00:01:06.000
<v Aaron>So that adds up over the course of old cranky man career.

00:01:07.000 --> 00:01:12.000
<v Joel>Absolutely, yes. So, this isn't like, "Oh," you know, "theoretically you should do this."

00:01:13.000 --> 00:01:17.000
It's like, no, I've literally been burned in bad ways in production, and I just can't take it anywhere.

00:01:18.000 --> 00:01:30.000
So, all this is to say, today's topic, we had another area where I see regularly people deviating how they handle local versus production.

00:01:31.000 --> 00:01:33.000
And I just wanted to see if it kind of falls into that same bucket for you.

00:01:34.000 --> 00:01:38.000
I'm going to let you kick it off, because I think this topic was your idea. But I was just sort of setting up some background for us here.

00:01:39.000 --> 00:01:47.000
<v Aaron>Yeah, I think that's a good point. So, I was looking at the service provider for something. I'm going to pick one of the tooling in Laravel.

00:01:48.000 --> 00:01:54.000
Let's say Telescope. And in there, there's a Gate functionality set up, and they may change it as we go through different versions.

00:01:55.000 --> 00:01:59.000
So, I'm not going to refer to the specific method names, but there's sort of like a gate functionality in there.

00:02:00.000 --> 00:02:06.000
And it was kind of set up that says, like, "Return true if you want someone to access this based off their user account. Return false if you don't."

00:02:07.000 --> 00:02:15.000
And by default, it's kind of built that it checks the user's email against an empty array, which is always going to be false. Okay.

00:02:16.000 --> 00:02:23.000
I don't like that. Because to me, that tells me that no one should be able to access Telescope, right?

00:02:24.000 --> 00:02:25.000
<v Joel>Mm-hmm (affirmative).

00:02:26.000 --> 00:02:34.000
<v Aaron>I mean, if the gate says who can access Telescope, and then it's configured that no one can. How come locally, when I go to /Telescope, I can see it?

00:02:35.000 --> 00:02:37.000
<v Joel>Oh, okay. All right.

00:02:38.000 --> 00:02:45.000
<v Aaron>And the reason is based off of their code further up in the process, there's a service provider that basically checks...

00:02:46.000 --> 00:02:53.000
That says, "I'm going to allow you access to this if," you know, "you're not local," or "if you are local," or "this gate matches."

00:02:54.000 --> 00:03:01.000
And that drives me nuts because I'm like, first of all, I don't like that it's different in local versus production. But second of all, here's the worst part.

00:03:02.000 --> 00:03:11.000
I don't know how I can actually test my logic that is actually working, that protects my production access. So, it's literally set up in a way that I can't...

00:03:12.000 --> 00:03:18.000
I guess maybe I can force it to the testing environment and write a test there. I'd have to look, but I don't know if it's... whatever.

00:03:19.000 --> 00:03:26.000
But I should be able to be restricted from accessed locally the same as I would be in production. And it wasn't clear.

00:03:27.000 --> 00:03:33.000
You have to look at the documentation, it's not even like in the comments of that. So, I don't understand the rationale or reasoning for that.

00:03:34.000 --> 00:03:41.000
That's kind of beyond my point. But it is an example of something that is not the same locally as it is in production.

00:03:42.000 --> 00:03:51.000
<v Joel>Right, yeah. And this is a good one, and it's not just Telescope. Like, you mentioned Telescope, but I think Horizon... Like, a lot of first-party Laravel...

00:03:52.000 --> 00:03:59.000
I don't know how to phrase it, but I think maybe Pulse is another one. Like, they're sort of meant to be used in a certain way.

00:04:00.000 --> 00:04:08.000
Like, bolted on to... It's not application functionality. I don't know if I'm... But it's like, there's this category of packages that follow the same pattern.

00:04:09.000 --> 00:04:13.000
And you're right. If you just look at the AppServiceProvider, because I brought it up while you were talking.

00:04:14.000 --> 00:04:23.000
The only hint that there's this special local-only behavior is, I think, the comment on the doc block says, "In non-local environments."

00:04:24.000 --> 00:04:29.000
So, you have to read between the lines a little bit and be like, "Oh, so it's different in local. Okay, but what does local mean?"

00:04:30.000 --> 00:04:37.000
And it actually means specifically APP_ENV equals the word local. Like, it's very specific to that.

00:04:38.000 --> 00:04:46.000
And I don't know about test either, but I think you're right. It might treat that production-ish. But, yeah, that's kind of a separate concern.

00:04:47.000 --> 00:04:50.000
Like, how it's sort of... hidden is too strong a word, but it's not obvious behavior.

00:04:51.000 --> 00:04:59.000
But it is a pretty radical departure between local and production. And you talked about the gate logic.

00:05:00.000 --> 00:05:03.000
I suppose... I'm just trying to think what the counterargument would be here.

00:05:04.000 --> 00:05:12.000
Like, if your gate logic truly was, "This one person's email address is whitelisted." You know, you could maybe say, "Wow, what could go wrong there?"

00:05:13.000 --> 00:05:17.000
But in a real app, it's probably more sophisticated, maybe checking your roles.

00:05:18.000 --> 00:05:21.000
<v Aaron>Yeah, probably roles or IP or a combination of those two things.

00:05:22.000 --> 00:05:23.000
<v Joel>Right.

00:05:24.000 --> 00:05:27.000
<v Aaron>And whenever there's any sort of logical combinations of stuff, I want to test it. Like I said, I just happened to think while I was talking.

00:05:28.000 --> 00:05:34.000
That maybe that doesn't... You could write a test. Like, a unit test against that. But again, I don't like that.

00:05:35.000 --> 00:05:40.000
That I would have a unit test that proves something works in a way that I can't actually exercise locally. Doesn't make any sense to me.

00:05:41.000 --> 00:05:45.000
I've seen them at the other direction, where it's like, I can use something locally, and I can write tests.

00:05:46.000 --> 00:05:54.000
But I maybe can't hit the production version of that, so I actually don't ever know if it works. But I've not seen the reverse, that is confusing to me.

00:05:55.000 --> 00:06:04.000
<v Joel>Yes. And I agree with you. Like, I want to be able to drive the app and kind of experience it the way a real user is going to experience it.

00:06:06.000 --> 00:06:17.000
So, just trying to anticipate what people might be thinking. First of all, the reason this is probably the default is it does reduce developer friction, right?

00:06:18.000 --> 00:06:23.000
So when I'm running this locally and I'm logging in, maybe with like a test account or some seeded account.

00:06:24.000 --> 00:06:33.000
Like, I don't have to keep going to my service provider and adding the email address and doing all the setup stuff. So, I understand that approach.

00:06:34.000 --> 00:06:44.000
But to me, all of the developer ease in the world immediately is invalidated the first time a bug hits production. Especially a security-related bug.

00:06:45.000 --> 00:06:49.000
So, I just tend to really... It's not that I don't like developer ease.

00:06:50.000 --> 00:06:57.000
But to me, it's such a lower priority than ensuring my system works correctly in a security context. Do you agree with my framing of that?

00:06:58.000 --> 00:07:08.000
<v Aaron>Yeah. I even bought into that even further. Like, I understood it and liked it when I first saw Telescope, when it was more of a manually registered thing.

00:07:09.000 --> 00:07:19.000
But now it automatically registers, unless you say, "Don't discover," I believe. So to me, that really was sort of, I don't know, it's just hard to...

00:07:20.000 --> 00:07:23.000
Like, I could install something. So I saw that, yeah, I could access it right away.

00:07:24.000 --> 00:07:33.000
Which is nice, but it was weird that I could access it right away before it was automatically available to me. So I think that that's the disconnection.

00:07:34.000 --> 00:07:38.000
If it was always automatically available to me, it would have made more sense to me that I could always access it immediately when I installed it.

00:07:39.000 --> 00:07:43.000
But it was like that was a separation that time in Laravel, I think. But, you know, you brought it up.

00:07:44.000 --> 00:07:52.000
You said, like, "This is a thing that maybe we don't really like." Do you remember what I did to try to get around that? Did you even like what I did?

00:07:53.000 --> 00:07:54.000
<v Joel>I vaguely remember what you did, but remind me.

00:07:55.000 --> 00:08:01.000
<v Aaron>Oh. Basically, when I saw this the first couple of times, I was okay with it, but it just kept bothering me. And I said, "You know, I just don't like this."

00:08:02.000 --> 00:08:09.000
"I want to see what it's like." And I wasn't using an email address. I was using roles and stuff like that, so I wanted to test that.

00:08:10.000 --> 00:08:19.000
So what I ended up having to do is go up inside of the actual service provider provided by Laravel's package, see how they were calling my gate functionality.

00:08:20.000 --> 00:08:28.000
And sadly, I had to go and copy that function that was calling that into mine and change it. So it was like, it would do three or four different things.

00:08:29.000 --> 00:08:32.000
As well as calling that gate. And I didn't like that, but it was the only way I could come up with.

00:08:33.000 --> 00:08:42.000
Is like, I had to say I would copy this exact same method into there and then just remove the one check for this local. And then everything worked as I expected it.

00:08:43.000 --> 00:08:53.000
<v Joel>Yeah, I think that's jogging a memory for me. And I think in later versions of either Horizon or Laravel, they did even narrow that down.

00:08:54.000 --> 00:09:02.000
So, it's like one function called gate or something, now that you just have to override that and get rid of that extra check it was doing for local.

00:09:03.000 --> 00:09:04.000
We basically don't make that call.

00:09:05.000 --> 00:09:11.000
<v Aaron>It was that. And there was also something where I probably should stop talking, because I may not even remember the details.

00:09:12.000 --> 00:09:14.000
But I thought there was something else in maybe Telescope, or something.

00:09:15.000 --> 00:09:20.000
Where it was like, it would make decisions on blacklisting or whitelisting, or including something based off the environment as well.

00:09:21.000 --> 00:09:27.000
And I was like, "I don't want that based off the environment." I want it always to function the same way, and I will configure things as I want them.

00:09:28.000 --> 00:09:30.000
And you know what, I will see locally, but the problem is before it goes to production.

00:09:31.000 --> 00:09:32.000
Right.

00:09:33.000 --> 00:09:36.000
Because if I'm logging my password or something like that, I want to see that locally, and I'll stop that there.

00:09:37.000 --> 00:09:44.000
<v Joel>Yeah, I agree. And you're right. These blend together because they're all slightly different but also mostly the same. So anyways, that's very...

00:09:45.000 --> 00:09:51.000
Anybody listening to this and wanting to take action. When you look at the actual code, it'll be apparent where the point is to override this.

00:09:52.000 --> 00:10:01.000
And I would just say maybe to wrap up. Like, if you're listening to this and you think this is old man says, "Get off my lawn," or whatever.

00:10:02.000 --> 00:10:04.000
You know what, you can believe that you'll run into these issues.

00:10:05.000 --> 00:10:10.000
Or maybe you will just lead a charmed life and never once run into one of the things that I've run into over and over and over.

00:10:11.000 --> 00:10:17.000
But trust me, Aaron and I are both saying this comes from hard-earned experience, and maybe listen to us.

00:10:23.000 --> 00:10:31.000
<v Aaron>Joel was just complaining about his AirPods. Something about putting one in and the second one in, I don't know, sometimes they work. I don't really...

00:10:32.000 --> 00:10:34.000
I wasn't really paying attention. But-

00:10:35.000 --> 00:10:36.000
<v Joel>Okay, thank you.

00:10:37.000 --> 00:10:43.000
<v Aaron>And he said, "Do you ever have that happen to you?" And I wasn't paying attention because, no, I don't use my AirPods like you do.

00:10:44.000 --> 00:10:45.000
<v Joel>You put them on your nose, or what do you do?

00:10:46.000 --> 00:10:52.000
<v Aaron>No, I only use one at a time. So, because I use them when I'm outside walking, I want to see what's going on, or I want to hear what's going on in the world.

00:10:53.000 --> 00:10:59.000
And we had this little weird conversation, like, you know, back and forth. Like, "Well, I don't need to..." And I was like, I wasn't mad, but I was like...

00:11:00.000 --> 00:11:01.000
And I wasn't judging, Joel.

00:11:02.000 --> 00:11:03.000
<v Joel>Okay.

00:11:04.000 --> 00:11:09.000
<v Aaron>But I was like, "Ah, maybe a little bit." Because for me, it was about safety. If I can hear people, you know, without both AirPods and whatnot.

00:11:10.000 --> 00:11:12.000
So, I don't know. I judge Joel a little bit there.

00:11:14.000 --> 00:11:19.000
But then I told him, "You know, I got to apologize to you for something else." Because I've been judging Joel a lot lately, and I don't know why.

00:11:20.000 --> 00:11:21.000
<v Joel>Oh, boy.

00:11:22.000 --> 00:11:23.000
<v Aaron>I'm going to tell you the other thing I need to apologize for.

00:11:24.000 --> 00:11:25.000
<v Joel>Yeah, I don't like this.

00:11:26.000 --> 00:11:32.000
<v Aaron>And I think it's because I was jealous. And it was actually a really great idea, and I didn't like that I didn't think of it.

00:11:33.000 --> 00:11:34.000
<v Joel>Oh.

00:11:35.000 --> 00:11:43.000
<v Aaron>The other day, we went out to have lunch, and we both ordered food. And I think Joel's food was way better than mine.

00:11:44.000 --> 00:11:48.000
And the reason I think it was way better is it was just amazing, little bites of food of all different types of stuff.

00:11:49.000 --> 00:11:55.000
And I ordered one entree. And Joel had ordered two appetizers. And I remember thinking like, "Joel, what's wrong with you? Why are you ordering two appetizers?"

00:11:56.000 --> 00:12:02.000
And he's like, "Oh, it's what I want." I'm like, "But is that going to be enough food?" And I just had all these different judgmental...

00:12:03.000 --> 00:12:11.000
It didn't feel judgmental, but it felt like trying to tell him that my way is better. Have one appetizer, maybe, and then have the main meal.

00:12:12.000 --> 00:12:18.000
And then he's sitting over here having his appetizer, two appetizers. I was a little upset. I was a little upset because they came out before my meal

00:12:19.000 --> 00:12:20.000
And so, he got his whole meal, whatever.

00:12:21.000 --> 00:12:22.000
<v Joel>Another hack.

00:12:23.000 --> 00:12:30.000
<v Aaron>But if we look back at the whole meal. I had some leftover in my meal, I wasn't really happy with it. Joel just demolished his.

00:12:31.000 --> 00:12:38.000
Was so happy the entire time, and made me jealous. So, "Oh, no. You won, and I apologize, Joel."

00:12:39.000 --> 00:12:50.000
I was wrong. You know, you don't have to just take our word for it. There's other people that can tell you how they've been bit in production too.

00:12:51.000 --> 00:12:52.000
And where would you find those people, Joel?

00:12:53.000 --> 00:12:57.000
<v Joel>Well, I'll tell you what, Aaron. There's some nice, smart devs in the Mastering Laravel community.

00:12:57.000 --> 00:13:02.000
And if you'd like to join, head over to masteringlaravel.io and click on community. We'd love to have you.