Skip to content

Instantly share code, notes, and snippets.

@ajcwebdev
Last active July 6, 2024 21:20
Show Gist options
  • Save ajcwebdev/e83763497981b7ce0763ec051e276a76 to your computer and use it in GitHub Desktop.
Save ajcwebdev/e83763497981b7ce0763ec051e276a76 to your computer and use it in GitHub Desktop.
CodingCat - Firebase Security Rules
showLink channel channelURL title publishDate
CodingCatDev
Firebase Security Rules
2024-06-03

CodingCat - Firebase Security Rules

Outline

Episode Description

Firebase expert Michael Dowden discusses security rules, architectural considerations, and best practices for building robust applications on the Firebase platform.

Episode Summary

In this episode, Michael Dowden shares his journey from early programming experiences to becoming a Firebase expert. He discusses the challenges of implementing security in Firebase applications, highlighting the differences between traditional backend systems and Firebase's approach. Michael emphasizes the importance of proper data structuring, security rule implementation, and testing strategies. He also covers advanced topics such as using Cloud Functions, event-driven architecture, and recent improvements in Firebase Storage security rules. Throughout the conversation, Michael provides practical advice and real-world examples from his experience building applications like FlexiPark.

Chapters

00:00 - Michael's Programming Journey

This chapter covers Michael Dowden's early experiences in programming, starting from his childhood encounters with a TRS-80 computer in the early '90s. He discusses his progression through various programming languages and technologies, including BASIC, C++, and Java. Michael shares anecdotes about his work digitizing library catalogs and creating websites in college, providing context for his eventual specialization in web development and Firebase.

12:35 - Introduction to Firebase and FlexiPark

Michael explains how he accidentally discovered Firebase while working on a parking management application called FlexiPark. He describes the process of building the app's UI and UX first, then integrating Firebase services like Realtime Database, Authentication, and Hosting. This chapter also delves into the concept of FlexiPark, discussing its target market of shared parking spaces and the challenges of building a serverless application that can handle varying loads.

19:26 - Firebase Security Rules and Architecture

This crucial chapter focuses on Firebase security rules and architectural considerations. Michael explains the different approaches to structuring data and implementing security in Firebase applications. He discusses the limitations and challenges of security rules, especially when dealing with complex data structures and access patterns. The conversation covers topics such as role-based access control, data organization, and the importance of considering security at every level of the application.

34:22 - Testing Strategies for Firebase Applications

Michael shares various strategies for testing Firebase applications, including manual testing, automated testing, and the use of emulators. He discusses the challenges of testing security rules and explains how Cloud Functions can be used to implement certain security measures that are difficult to test with rules alone. This chapter provides practical advice for developers on how to ensure the security and reliability of their Firebase applications.

37:12 - Advanced Firebase Techniques and Cloud Functions

This chapter explores more advanced Firebase techniques, focusing on the use of Cloud Functions and event-driven architecture. Michael discusses different approaches to implementing administrative functions, data integrity checks, and background processing. He provides examples from FlexiPark, such as using Cloud Functions for image analysis and metadata extraction. The conversation also covers the trade-offs between using Cloud Functions and client-side security rules.

46:15 - Recent Improvements in Firebase Storage Rules

In the final chapter, Michael highlights a significant improvement in Firebase: the ability to use Firestore data in Storage security rules. He explains how this feature has simplified the process of securing files in Storage buckets and reduced the need for complex workarounds. This chapter demonstrates how staying updated with Firebase's evolving capabilities can lead to more efficient and secure application development.

48:37 - Conclusion and Perfect Picks

The episode concludes with the hosts sharing their "perfect picks" - personal recommendations unrelated to the main topic. They discuss "The Last Dance" documentary series about Michael Jordan and the Chicago Bulls, as well as LEGO sets designed for adults. This lighthearted conclusion provides a break from the technical discussion and offers insights into the hosts' personal interests.

Transcript

00:00 - Michael's Programming Journey

[00:00] Welcome back to CodingCat.dev, where
[00:04] we give you cats, the freshest dose of dev snacks.
[00:08] Brought to you by Cloudinary.
[00:09] Build faster with AI-powered image and video APIs.
[00:12] What's up, perfect peeps?
[00:17] Continuing our month of Firebase here.
[00:20] So chatting all about Firebase security rules
[00:23] today with Michael Dowden.
[00:25] What's up, Michael?
[00:26] Hey, how's it going?
[00:28] It's going well.
[00:29] I'm excited to have you on.
[00:31] You were-- I reached out to a bunch of Firebase folks,
[00:33] and you were the first one to excitedly come back.
[00:35] I'm like, we have more Firebase peeps.
[00:39] So just want to get to know you a little bit more
[00:43] and how you went down this path, as many of us
[00:46] have over the course of the years.
[00:49] And get a little bit to--
[00:51] yeah, get to know you a little better.
[00:52] So how did you get started in this crazy development world,
[00:57] first of all?
[00:59] Well, in the development world?
[01:01] Wow, that--
[01:03] It'll take you back.
[01:04] It's always tricky.
[01:05] The more gray hairs we get, it really takes you back.
[01:10] That started back in the, I want to say, early '90s.
[01:16] I bought a Trash 80, good old handy TRS-80 computer,
[01:21] put it together.
[01:22] And it was one of those that had BASIC on board,
[01:27] and they didn't have a lot of software for it.
[01:28] So I would go to the library, check out
[01:30] a book that had the source code for a video game,
[01:34] and you would type it all in--
[01:36] No way.
[01:36] --so that you could then play the video game.
[01:39] And that was literally--
[01:41] yeah, that was literally how I started programming.
[01:44] So is that a library thing?
[01:46] Or how do you even--
[01:47] I always wondered back in the day,
[01:49] how did you even learn about the book to go get it?
[01:53] There wasn't internet back then, just for those kids
[01:56] that are listening.
[01:58] Probably.
[01:59] Libraries were the best.
[02:00] Yeah, you would go talk to the librarian,
[02:03] or you would go look through the card catalog
[02:06] and find computer books.
[02:08] But back then, they had programming books,
[02:11] and they had program books, the ones
[02:13] to teach you how to program, and the ones that were
[02:15] the program in printed form.
[02:18] That is insane.
[02:21] Debugging is really hard, because if you
[02:23] make a typo or something, now you've
[02:24] got to figure out where was the mistake,
[02:26] and the old basic programs like that were not super forgiving.
[02:32] So it was challenging.
[02:35] And nowadays, the biggest complaint
[02:37] is my internet's too slow to download these 800-gig files
[02:41] or whatever.
[02:43] Well, that's amazing.
[02:44] Back in my day, we didn't have internet.
[02:48] Yeah, the old dial-up modem sound, that's what I was--
[02:51] so OK, video games are one thing,
[02:53] and that drives you to want to punch in some code
[02:57] and learn about a video--
[02:58] or how to make a video game.
[02:59] But why did that then translate to, oh, I could be a programmer?
[03:04] Did you go into high school and start learning programming?
[03:09] Or what was your first steps to learning the actual code?
[03:13] Yeah, so I started there just because it was super cool to do
[03:18] and then--
[03:19] super cool for a nerd, I guess.
[03:23] But I kept with it.
[03:25] So I started with the ROM basic on the TRS-80,
[03:29] and then I moved to more modern versions of basic.
[03:34] My parents finally bought a computer, an old 386 computer.
[03:38] And I learned basic and QBasic and QuickBasic,
[03:44] and eventually bought a copy of--
[03:49] was it Turbo C++--
[03:51] and started doing a lot of coding with that,
[03:55] just to teach myself how to do stuff.
[03:57] And I built some software with it.
[04:01] I actually sold some software.
[04:02] Shareware was hugely popular back then,
[04:05] so I actually built and sold some software on AOL
[04:09] at the time.
[04:10] Wow, that's incredible.
[04:11] And did that before college.
[04:14] And it just became one of those things that--
[04:18] it was one of the first things in my life
[04:20] where I'm like, this is something
[04:21] that I really enjoy doing, but I'm also really good at.
[04:25] It makes sense to me.
[04:27] And it was one of the few things that I was interested in
[04:33] my father encouraged me to do, because I
[04:35] think that he understood, hey, this
[04:37] is going to be a big deal soon.
[04:40] And it wasn't really a big deal at the time in terms
[04:43] of people weren't talking about this amazing career
[04:46] in technology, but he encouraged me to keep doing it.
[04:50] I love doing it.
[04:51] So I eventually went--
[04:53] when I started looking for colleges,
[04:54] I'm like, I want to go and get a degree in computer science.
[04:57] And I did that and never looked back.
[05:02] And one of the things that I did in high school that
[05:06] helped a lot is I got a job working for a library.
[05:10] And my job for the library, hilariously,
[05:14] was data entry, because this was really, really early
[05:18] in the digitization of libraries.
[05:20] So they have all these physical card catalogs,
[05:23] and they're trying to move them all into electronic records
[05:26] so that libraries can communicate over modem dial-up,
[05:32] but over BBS systems and everything.
[05:34] But they wanted to be able to communicate digitally on, hey,
[05:37] who has what books?
[05:38] Yeah, 100%.
[05:40] And so I personally entered all of the metadata
[05:44] for around 10,000 books at this small community library.
[05:50] So I'm going to embarrass myself right now.
[05:52] What is it called, the cataloging system?
[05:54] I can't even remember it anymore.
[05:57] The old card catalog.
[05:58] Yeah, isn't there--
[05:59] It was literally all these little tiny cards
[06:01] in long drawers you'd pull out and flip through,
[06:05] and they had to be--
[06:06] you would have them by author name or by subject
[06:09] or all these different ways of looking things up.
[06:12] And so each book would have multiple cards in there.
[06:15] But I would just go grab stacks of books off the shelf,
[06:18] set them down, flip through, and type in all the information
[06:21] into this computer program.
[06:22] And we would ship them in disks back to the central office
[06:26] to be loaded into the system.
[06:27] I just had to Google my thought.
[06:30] So Dewey Decimal System is--
[06:32] Yes, Dewey Decimal.
[06:34] It was totally out of my mind.
[06:35] I couldn't remember it.
[06:36] But I always found in the library,
[06:39] the Dewey Decimal System, the most confusing thing
[06:42] I had ever dealt with.
[06:43] I'm like, why am I going after this number dot something?
[06:47] What is happening right now?
[06:49] But yeah, that's pretty incredible to get started
[06:51] in that side of things.
[06:53] So in college, did you specifically
[06:55] choose a CS major then that you went towards?
[07:00] I did.
[07:01] And I really-- so I started--
[07:05] my first, especially the internet, was like ALL,
[07:07] like I said.
[07:08] And then I get to college, and we had internet access,
[07:12] but it was very, very limited.
[07:14] And it wasn't until my sophomore year
[07:17] that they started pulling ethernet into the dorms
[07:21] so that you would actually have internet access from your dorm
[07:24] rooms.
[07:25] Otherwise, you had to have your own dial-up service right
[07:27] there in the dorm room, which I actually
[07:29] did for my freshman year, just so I
[07:31] would be able to get out and do stuff, because I was already
[07:35] kind of in that mindset.
[07:36] So one of the first professional--
[07:40] I did a lot of kind of odd jobs around campus.
[07:43] Like my sophomore year, I helped install ethernet cards and stuff
[07:47] for other students.
[07:49] But I think it was my junior year,
[07:51] I got a job working for one of the IT guys who
[07:59] was responsible for some of the internal systems.
[08:01] And one of the things that I did is
[08:03] I helped him take the entire school directory
[08:10] and digitize it and put it online as a website
[08:14] so that they could stop printing.
[08:16] They were printing these massive directories
[08:18] of all the faculty and staff and all the different numbers
[08:21] and all the students.
[08:22] And because it's changing potentially every semester,
[08:24] they were reprinting those once a year, at least.
[08:28] And it was tens of thousands of dollars
[08:30] to print all of these and have them everywhere.
[08:32] The yellow page on campus every semester, holy smokes.
[08:36] So it was kind of a no-brainer.
[08:38] But that was one of my very first paid gigs
[08:42] in doing something on the web.
[08:43] And I just kind of kept going that route.
[08:46] My first job out of college was working
[08:48] for a software consulting company building web apps.
[08:52] And the rest is history.
[08:55] I've really never done anything that was not directly
[09:00] related to doing web work.
[09:01] But I was one of the first kind of generations
[09:04] of people that started the career on that line
[09:07] and then never looked back.
[09:08] Yeah, that's really cool.
[09:10] And what kind of tools were you using back then?
[09:13] Was it just raw HTML and JavaScript?
[09:17] Or was it something else at that point?
[09:20] So in the really, really early days, we were using--
[09:25] oh, I'm going to draw a complete blank of what it's called.
[09:27] We would actually use C programs for the back end.
[09:32] And there was this hook to the web server
[09:37] so that the web server would take a URL
[09:41] and pass it off to the C program to do the manipulation
[09:43] and send it back.
[09:44] I am literally blanking what the name of the technology
[09:47] was called.
[09:47] But I wrote some of my first websites in C and HTML.
[09:51] That is just incredible.
[09:53] I just had a pod with somebody very high up
[09:57] on the Perl side of things.
[09:59] And it's just like, these are not technologies
[10:01] that people write anymore.
[10:03] I'll talk to engineers, and they're
[10:05] writing C and C coding and stuff like that that are still
[10:08] C-based or something that's somewhat similar to that.
[10:11] But that's not a web thing anymore.
[10:13] So it's kind of interesting.
[10:15] So as you continued up through that career path,
[10:19] where did you head to next from a programming standpoint?
[10:22] Was it like Java, or did you kind of--
[10:25] Yeah.
[10:25] OK.
[10:26] Yeah, I moved straight into Java when
[10:29] I got my first consulting job.
[10:31] And I dabbled in lots of different things.
[10:34] So I learned TCL, which is a programming language that very,
[10:39] very closely mirrors--
[10:42] it may actually be POSIX compliant,
[10:43] but it looks like a command line.
[10:46] So it looks like you're writing command lines.
[10:48] That's for folks, because I had never heard of it.
[10:51] There you go.
[10:52] I did-- yeah, right?
[10:53] Exactly.
[10:55] So I learned that.
[10:56] I learned ColdFusion.
[10:58] That was one of the other systems we used.
[11:02] And then Java.
[11:03] Java ended up being the bulk of my career,
[11:05] but I did work with ColdFusion for a while.
[11:07] And like everyone, I worked with PHP some,
[11:11] because that's just kind of the language of the internet.
[11:13] It has been for a really long time.
[11:16] It wasn't until probably 2015, 2016
[11:23] that I really started moving out of Java
[11:25] more into straight JavaScript ecosystem
[11:28] and pretty quickly adopted TypeScript.
[11:29] So I'm doing mostly TypeScript now--
[11:32] Node.js and front-end coding.
[11:35] Awesome.
[11:36] That's probably a great point to pause and get our [INAUDIBLE]
[11:41] and then we'll come back and talk about what you're
[11:43] working on now with Firebase.
[11:46] Cool.
[11:47] Cloudinary allows you to remove any unwanted backgrounds
[11:50] so you can reuse assets efficiently.
[11:53] You can also erase objects and people
[11:55] from images for placement in new experiences.
[12:02] For more engaging content, easily turn static images
[12:06] into dynamic animations.
[12:08] And rely on smart cropping to always deliver assets
[12:11] with a focus on the most relevant objects to your brand.
[12:15] Cloudinary Programmable Media.
[12:17] Build faster with AI-powered image and video APIs.
[12:21] Huge thanks to Cloudinary once again
[12:27] for not only sponsoring the podcast,
[12:29] but hosting all of our images for years and years now.
[12:32] Huge.
[12:33] Thank you.

12:35 - Introduction to Firebase and FlexiPark

[12:35] So we kind of broke down Michael's history
[12:38] of just kind of how he became a developer all the way back
[12:41] in the days of pre-internet.
[12:44] And it kind of led us all the way
[12:46] to the future, which we're in now, of TypeScript world.
[12:49] And I think I'm kind of interested how
[12:53] you made it into the Firebase land to get started there too.
[12:59] Accident.
[13:00] Completely by accident.
[13:03] So 2015, we were starting to kick off the consulting company
[13:09] I'm currently working for that I founded with my partner,
[13:11] Andromeda.
[13:13] And one of the early product ideas
[13:17] was actually pitched by my father-in-law, which
[13:19] is for a parking startup, which we have since spun up.
[13:23] It's called FlexiPark.
[13:25] And as we were building out that app,
[13:28] we did something that makes a lot of sense.
[13:30] We started from the UI and the UX of it.
[13:34] So we built out these web pages that didn't do anything.
[13:37] We put them in front of people and let them interact with them
[13:41] so we could get that user feedback really, really early.
[13:43] And then we attached it to Google Analytics
[13:49] so we could get analytics of how people are using it.
[13:51] We did a lot of stuff with local storage
[13:53] so you could save state and things
[13:54] and make it look like it was functioning as an app.
[13:57] And they were like, OK, now what's the next step?
[13:59] And one of the guys we were working with to build it,
[14:03] Michael McGinnis, is like, hey, I
[14:05] heard of this cloud-based database called Firebase.
[14:09] I think you should check that out.
[14:11] I think that sounds like it may be the right thing for this.
[14:13] And at that time, it was the Realtime Database.
[14:16] It was the only real major service offering.
[14:19] But that was huge.
[14:20] We were already using JSON data to power the whole thing.
[14:24] I'm like, wow, I don't have to do very much work at all.
[14:27] I can literally just take these data structures
[14:30] and dump them straight into the database, and we're online.
[14:34] And Firebase had the hosting service at that point
[14:37] and the auth service.
[14:38] So we tied in the auth service, dumped everything
[14:40] in the database, threw it on Firebase hosting,
[14:43] and we had the first version of the application.
[14:46] We didn't even need to use Cloud Functions at that point
[14:48] because our payment system was using
[14:52] PayPal, which was a pure front-end integration
[14:55] at the time.
[14:57] Done.
[14:58] We got the app live, got our first set of stuff.
[15:01] Nope, that is not actually it.
[15:04] Sorry.
[15:05] F-L-E-- nope.
[15:06] And there is the second one.
[15:08] Flexi Park with an I. And so it's worth noting,
[15:11] we existed long before that other one.
[15:14] We have claimed so many similar-sounding domains,
[15:18] but it doesn't keep copycats from showing up.
[15:21] And it sure did happen.
[15:23] So break this Flexi Park down a little bit.
[15:26] I feel like I've had this idea on and off for years.
[15:29] I own some crazy park and ride domain at one time
[15:33] because I want to do something like this.
[15:35] Totally.
[15:36] So break down kind of how people use it
[15:38] and why that works so well for Firebase.
[15:41] So Flexi Park is a full-service parking management
[15:47] application, and our target market is shared parking.
[15:53] So our customers, our clients who are the property owners,
[16:00] are generally small businesses or nonprofits
[16:03] that have a parking lot in a high-traffic area.
[16:05] They're not using it all the time.
[16:07] So one of the craziest stats that I ever looked up
[16:10] is if you have a 9 to 5 business,
[16:13] you're utilizing your parking just 25% of the time.
[16:16] It's literally sitting idle the other 75%
[16:19] of the time, which is just mind-boggling, but true.
[16:23] And so we started working with small businesses.
[16:25] Hey, let's make money from your lot the rest of the time.
[16:28] And it's a really big deal, and it turns out
[16:32] there is a ton of research in the parking
[16:36] industry around this concept.
[16:38] But at the time, there were very few companies
[16:41] doing anything with it.
[16:42] And the other thing that's still, to this day,
[16:45] very true in the parking industry
[16:47] is that there's really very little focus on user
[16:50] experience.
[16:51] And there's a lot of really horrible user experiences.
[16:54] So we started from that, from the get-go,
[16:57] so that the parking experience from the user side
[17:00] was as simple and friendly as possible,
[17:04] and just kind of kept rolling with it.
[17:05] So the biggest challenge you run into in this situation,
[17:08] of course, is do you have good internet access
[17:11] at different locations and stuff like that?
[17:13] But it's all very lightweight, but you also
[17:18] end up with really big spikes, right?
[17:19] Because most of the week, your bulk of your parking
[17:26] is going to be monthly subscribers.
[17:27] But monthly subscribers, you're not
[17:29] interacting with them every single day, necessarily.
[17:33] But you also have a lot of enforcement people.
[17:35] So you've got to have enforcement people who
[17:37] can go around and do their stuff.
[17:38] And then you'll have a big weekend,
[17:39] like a holiday weekend or something,
[17:41] and you'll end up with just thousands of transactions,
[17:44] whereas maybe a normal day is 50.
[17:47] You'll be able to handle those ridiculous different balances
[17:52] of load, and serverless works really well for that.
[17:54] So how many different areas into your application are there?
[17:57] I assume there's a back end for the people who
[18:01] have parking spaces, the small businesses.
[18:04] You have a-- I just said back end,
[18:07] but another portal for myself if I wanted to come in and park.
[18:11] But then the enforcer side of that, too,
[18:13] there must be a ticketing person view, too, huh?
[18:18] Correct.
[18:19] And then there's the admin or support side as well.
[18:22] Gotcha.
[18:23] So that's-- are you guys running that admin side help desk
[18:29] piece to this all as well?
[18:31] Yes.
[18:33] So we're running the whole thing,
[18:35] and that's just like one business.
[18:39] Our consulting business is our primary thing that we do,
[18:41] but we've got other apps that we work on.
[18:45] And Andromeda's primary business is actually
[18:48] building digital products for companies
[18:51] and helping them ramp those up.
[18:53] So that may look like doing just UX and UI
[18:57] for established companies that have their own back end system.
[19:00] So we do that, and that's fine.
[19:01] But we have also built a lot of full stack products
[19:06] on Firebase for customers as well.
[19:10] And so we've been working with a really exciting startup out
[19:13] of California to build--
[19:18] literally build a startup from ground zero.
[19:20] Oh, wow.
[19:20] And that entire product is built on Firebase.
[19:23] That sounds incredible.
[19:24] That's really neat.

19:26 - Firebase Security Rules and Architecture

[19:26] So let's start to break down, even if we use FlexiPark
[19:30] as a great example, some of these security rules
[19:35] that we start to talk about in Firebase.
[19:37] It's kind of interesting, and maybe I
[19:40] should pop this up for anyone who hasn't seen it.
[19:43] This seems crazy small to me today.
[19:45] I don't know why.
[19:46] My eyes are probably failing, as always.
[19:49] But as you can see here, when you
[19:51] start talking Firebase security rules,
[19:53] you start to talk about Cloud Firestore, real-time database,
[19:56] cloud storage.
[19:58] And there's always these two pieces to it-- in my mind,
[20:03] at least.
[20:03] I know you've been doing this a lot longer than I have,
[20:06] but there's always the front-end side
[20:08] that you could think about that you're putting
[20:11] all these security rules to.
[20:12] But then if you have to deal with Cloud Functions
[20:15] or anything, there's the admin SDK that says,
[20:18] eh, I don't follow any of that.
[20:21] I'm just going to do whatever I want,
[20:24] because I'm the admin API.
[20:26] And then there's that side of it.
[20:27] So can you help me break down for people
[20:30] what I'm actually trying to say there?
[20:33] Yeah.
[20:33] So one of the first things you have
[20:36] to decide when you're going to architect
[20:38] an application on Firebase is, where
[20:43] do I want my touchpoints with the database to occur?
[20:46] And how am I going to apply security around those?
[20:48] And there's lots of different ways you can look at this.
[20:50] You could-- and this is-- I see a lot of, especially people
[20:56] working with Firebase for the first time,
[20:58] basically treating it like any other back-end system.
[21:01] I'm going to create this entire API layer.
[21:04] It's going to be all of these REST calls.
[21:07] And I'm going to support that API layer with Cloud Functions.
[21:12] And I'm going to apply standard REST types of security.
[21:15] But the admin SDK at that point in time
[21:18] is doing all the heavy lifting, getting data
[21:20] in and out of the database or storage bucket or whatever.
[21:25] But I don't like that approach very well
[21:30] from the standpoint of building really
[21:33] rich, interesting applications.
[21:35] It works fine.
[21:36] It's very straightforward.
[21:38] It simplifies a lot of things.
[21:40] But you're missing out on a lot of the really great features
[21:46] of the platform when you go that route.
[21:49] And I've also started really appreciating
[21:53] the more event-driven options within the Cloud Function
[21:58] ecosystem.
[21:59] And I've been really excited to see--
[22:02] I've been on the advisory board for serverless architecture
[22:05] conference since 2019.
[22:08] And one of the things that I've gotten to observe
[22:11] since that time as the whole serverless ecosystem has
[22:15] progressed is this focus on, well,
[22:19] serverless is really just the next phase of microservices
[22:24] into--
[22:24] serverless is really this event-driven paradigm.
[22:28] And I generally advocate for that.
[22:31] But within the Firebase ecosystem, what that means
[22:34] is you're potentially putting more
[22:39] of a load on your client, whatever that may look like,
[22:43] whether that's a mobile application or a web
[22:44] application or even a game.
[22:48] There's lots of different front-end options for Firebase.
[22:52] And at that point, your security layer to your database
[22:57] or to your files in your storage bucket
[23:00] is based on security rules.
[23:03] And one of the biggest challenges
[23:07] I've seen is when you're trying to get started in this, hey,
[23:11] how do I do some of the really sophisticated types of security
[23:15] that I could have done in another system?
[23:18] How do I do that with rules?
[23:20] And a couple of years ago-- so I guess it was 2021 now--
[23:25] I put together a blog post and a video
[23:28] introducing how you can do authorization models using
[23:33] rules.
[23:34] So that can be access control lists,
[23:37] role-based access control.
[23:40] And what does the data structure need to look like?
[23:42] What do the rules need to look like in order
[23:45] to get this fairly rich role-based type
[23:48] of authentication implemented in rules?
[23:53] And it is possible.
[23:54] I had some people pretty convinced
[23:57] that it wasn't possible until I put that together.
[24:01] That's kind of a big deal.
[24:02] And it's important to note that you can do that,
[24:04] that you can be really sophisticated with it.
[24:07] But it isn't without its own challenges
[24:10] because there are a lot of limitations
[24:17] to how many times you can call specific functions
[24:23] within the rules.
[24:25] So there's the concept of a get function or an exist function,
[24:29] which will actually query a location in the database
[24:33] in order to test what's there.
[24:35] And so you want to structure your rules in such a way
[24:39] that you're minimizing how many times
[24:41] you do those types of lookups.
[24:43] So it takes what might have been a really straightforward, nice,
[24:46] dry style of coding.
[24:49] And you just get rid of all that.
[24:51] And you have to completely optimize
[24:52] your rules for what works based on the limitations.
[24:57] The other thing you run into when
[24:59] you start writing your really complex storage rules,
[25:01] or database or storage rules for the first time,
[25:05] is that your data structures, the way
[25:09] you choose to store data in the database,
[25:13] will have a direct bearing on how
[25:16] you're able to write those rules.
[25:17] Now, Firestore has made that a lot easier.
[25:20] Realtime Database was brutal for this.
[25:23] Because in the Realtime Database,
[25:25] if you query a point in this massive--
[25:28] well, it's basically a massive JSON object.
[25:30] You query any point on that, and you get that point
[25:32] in everything it contains.
[25:34] And so you had to do a lot of artificially flattening
[25:39] your data structures so that you could have more fine-grained
[25:41] control over what was where.
[25:43] The document structure in Firestore
[25:45] makes that a lot nicer.
[25:46] You can say, I want to give access
[25:48] to exactly this document, or this document and everything
[25:51] underneath it in the path, which is very useful.
[25:55] The one thing in Firestore that I still find challenging--
[25:58] and we can talk about this a little further
[26:00] and break it down, but the--
[26:03] so it's a document collection model, for those who don't know.
[26:07] And in that, you can actually do what's called a subcollection,
[26:11] essentially.
[26:12] So within a document, you can have another collection
[26:15] of documents.
[26:17] And the interesting part for security rules and all that
[26:21] to really start to wrap your head around,
[26:23] if I give access at this level, do they get it at this level?
[26:27] Can you talk through, mentally, that's
[26:31] a little challenging of what data you're getting,
[26:34] and especially when you talk about costs, too.
[26:37] I feel like there's a cost to all of that as well.
[26:41] So from how you approach the architecture of it,
[26:46] using more of a concrete example,
[26:48] because this happens a lot.
[26:49] Let's say you're going to have a user object.
[26:51] So you're going to have users slash the UID of that user.
[26:55] And then they're going to have things
[26:57] that they own or control underneath that level.
[26:59] That's a pretty common structure that I see.
[27:02] And so you may want to say, hey, if I'm that user,
[27:08] I should be able to read and write everything
[27:11] underneath that, because that's the data that I own and control.
[27:14] And there's nothing wrong with that,
[27:17] except it means that you can't put any data
[27:22] under that location that's related to things you don't
[27:27] want the user to change, such as their roles or access
[27:31] or permission, or maybe their--
[27:35] if you've got a--
[27:37] I don't know if I just blipped for a second.
[27:53] Yeah, let's just rewind.
[27:55] You started talking about their roles.
[27:57] Yeah.
[27:59] So you don't want to put roles or access information
[28:04] underneath the user location, because they
[28:07] could change that, potentially.
[28:09] They could give themselves a higher level of access.
[28:10] If it's a subscription-based model,
[28:12] you don't want any of that subscription data
[28:14] to be inside of that location.
[28:16] In fact, you potentially don't even
[28:19] want to store the user's receipts
[28:22] underneath that location, their user location,
[28:24] because they could change that stuff.
[28:29] And so now you have to start thinking,
[28:31] based upon the way you want to provide the rules,
[28:33] if you want to say, hey, I want my users to just have
[28:36] read/write access to all of their own data,
[28:39] and I want to put all that underneath that user location,
[28:42] that's fine.
[28:43] But now it means you have to move out
[28:44] your access and your receipts and all your subscription
[28:47] stuff elsewhere.
[28:48] It's got to be someplace completely separate
[28:49] in the application.
[28:51] And it has to have completely different collection
[28:54] names than the names of the collections that
[28:56] are underneath the users, because you may very well
[28:59] find yourself wanting to do collection group queries.
[29:02] And the way collection group queries work in Firebase,
[29:06] which is a great feature, is any collection that
[29:10] has this specific name, regardless
[29:13] of where it is in the overall hierarchy of the database,
[29:16] I want to query that, and I want to return stuff back,
[29:20] which is awesome.
[29:21] But if you have collections under your users object,
[29:26] for example, that have a name of, I don't know,
[29:29] my documents, but then you have system-level documents that
[29:33] are someplace else, you could very easily end up
[29:36] in a situation where you can't run that query in a way that
[29:39] would ever pass the security rules.
[29:43] And one of the important things about security rules
[29:45] in Firebase is that they are not filters.
[29:50] So if you end up running a query that would return records
[29:56] a user doesn't have access to--
[29:58] let's say they have access to three of the records,
[30:00] but not one of the records--
[30:02] the entire query will fail, because they didn't have access
[30:05] to all those permissions.
[30:06] The way we, as developers, might prefer it to work
[30:09] is, I'm going to query for all those records.
[30:12] The rules are going to say, I only have access to these three,
[30:16] so those are the only ones I'm going to return.
[30:18] But that's not the way Firebase works.
[30:20] And so it's up to us to make sure
[30:22] that the filters on the query are only
[30:25] going to select documents that we have permission
[30:27] to according to the rules.
[30:30] Which, that piece right there, it always frustrates the heck
[30:33] out of me.
[30:35] And so it's some--
[30:36] Number one mistake, I see.
[30:38] And some of the interesting things in there,
[30:40] too, is that when you start talking about--
[30:43] we're talking primarily around security,
[30:45] but from an architecture perspective,
[30:47] you start putting those collections
[30:48] in and doing searches based on just the name of those,
[30:53] you start also hitting all of those, too.
[30:55] So there's a cost for reads on that.
[30:57] That becomes really high all of a sudden, as well.
[31:00] So there's a few things in there that, myself,
[31:04] coming from a SQL world--
[31:05] I don't know if you're from there, too--
[31:08] those are very simple database calls.
[31:11] And the interesting part is, you also
[31:15] have to be constantly considering the fact
[31:18] that this was all written for, I won't say wide open,
[31:22] but basically like, hey, I've got your API--
[31:25] not API key, but application ID and things like that.
[31:28] And I can hitch into your system any time I want to.
[31:32] So you need to make sure everything is secure.
[31:34] It's not like a, here's a database.
[31:37] We have a middle tier that will protect it all based on API
[31:42] and access, or ACLs, or RBAC, or however you want to look at it.
[31:46] This is completely open.
[31:47] And you need to make sure all of those calls and pieces,
[31:50] especially that user ID example, are secure.
[31:54] So it's hugely important.
[31:56] I always tell people, when Firebase was first--
[31:59] when we were putting out databases,
[32:01] they were completely insecure.
[32:04] I don't know why they chose that route.
[32:06] But they're like, yeah, it's up to you.
[32:08] Make sure it's secure later on.
[32:10] And it's like, whoa, wait a minute.
[32:12] Let's start to get our arms around that.
[32:14] And they've corrected over the years.
[32:16] I think they've-- most recently, they
[32:18] put it in a secure state.
[32:21] And then they were doing, hey, if you
[32:22] want to do more of a development mode,
[32:25] it'll be completely open up until this date.
[32:28] So they do like 30 days and then lock it down to make sure.
[32:32] So there's some things in there.
[32:33] But just the concept as a whole of, here's a database.
[32:37] Do what you want with it, it can be a little frustrating
[32:40] to get going on.
[32:42] Yeah, so I came from the SQL world, too.
[32:44] And I think the hardest challenge that I had personally
[32:47] moving into Firebase is wrapping my head
[32:50] around the different ways of approaching data structures
[32:54] when you're dealing with that document collection
[32:56] model instead of the relational model.
[32:58] And so many places--
[33:02] I see so many places with databases and just back
[33:05] end systems in general.
[33:07] Oh, we have a VPN.
[33:08] That's our security.
[33:10] Whereas in this world, it's all out there live on the internet.
[33:13] And you're in a zero-trust model.
[33:15] And you have to treat it like a zero-trust model.
[33:18] And like you said, put the security at every single point.
[33:22] It's a different way of thinking about things.
[33:24] And I don't want to say it's easier to make a mistake.
[33:30] I think it's easier to make a mistake when you're moving
[33:33] into it just because you haven't yet learned the things you
[33:35] need to look out for.
[33:38] But it can be very secure.
[33:40] You've got to really test for it.
[33:42] You've got to prioritize that.
[33:44] Yeah.
[33:44] I almost wish there was a little bit more maybe like a CLI
[33:48] or something to say, hey, are you
[33:50] setting up this type of like an MVC project for blah?
[33:55] Would you like us to set up like a user and a profile
[33:58] and blah, blah, blah for you?
[34:00] Like some sort of flow to it a little more.
[34:02] And then there's like, oh, I can work within this Firebase
[34:06] security set of things.
[34:07] Sure, that makes more sense to me instead of just
[34:09] blank page all the time.
[34:10] So for people who are looking for that,
[34:13] like go into Firebase's GitHub examples.
[34:16] And there's tons of them out there.
[34:18] There's just not really a workflow
[34:20] to get you into those.

34:22 - Testing Strategies for Firebase Applications

[34:22] How are you going about, and maybe you're not
[34:25] with like Flexi Park, but like with some
[34:28] of your other systems in testing security rules?
[34:31] Are you guys writing unit tests and going down that road?
[34:35] Yep.
[34:36] So we have a wonderful QA lead at Andromeda.
[34:41] And they do a great job of putting together
[34:45] scenarios for data access and different things.
[34:49] We test it.
[34:50] We do manual testing.
[34:52] We do some automated testing.
[34:53] But we're really looking at what are the different avenues.
[34:55] And so we do a lot of that way.
[35:00] We will also-- like we utilize emulators a lot.
[35:05] And we started utilizing the emulators a lot more
[35:09] for testing because you can pre-set up all of your test
[35:14] data in the emulator, spin up the emulator,
[35:16] and your test data is there.
[35:17] And you decide that you need to reset.
[35:19] You just shut your emulator down, spin it back up,
[35:21] and you've got a clean slate, and you can continue working.
[35:24] So we do that a lot.
[35:26] It gives you a great way of testing things.
[35:28] We'll utilize the rules simulator inside
[35:32] of the Firebase console quite a bit.
[35:34] That's a great way to kind of figure out
[35:37] some things with relation to putting your rules together.
[35:41] And to some extent, you're really
[35:44] just applying solid logic.
[35:48] It's important to break things down in a way that
[35:50] is a little bit testable because you can't really run unit tests
[35:52] directly against the rules.
[35:54] You have to deploy the rules and then
[35:58] test the different types of access you might want to do.
[36:01] Yeah, I think that's one of the most challenging things
[36:05] in the Firebase realm to do that testing.
[36:09] I think more tools are just--
[36:12] I'll say generic, but that's the wrong word.
[36:14] It's become so common for SQL-based testing tools
[36:19] and things like that to be part of it,
[36:21] whereas Firebase is its own animal completely.
[36:25] And so there's not as many of those scenarios spelled out.
[36:29] I think you can go a long ways with the different SDKs
[36:32] that you have in testing and things like that,
[36:34] but it's always a challenge.
[36:37] QA is always a challenge, and there's
[36:39] a reason I never wanted part of it.
[36:42] And honestly, that's one of the decisions--
[36:44] like we mentioned at the very beginning of this conversation
[36:47] about how to approach security, one of the decisions
[36:50] you can make is, this is such an important thing for me
[36:54] to test in an automated fashion, and I can't do that
[36:57] with a security rule, that I'm going to take this bit of code
[37:00] and I'm going to put that in a Cloud Function
[37:03] and throw automated unit tests at it
[37:05] just so that I can automate that testing.
[37:07] And that's a perfectly valid, rational reason to do that.

37:12 - Advanced Firebase Techniques and Cloud Functions

[37:12] And when we're building applications,
[37:16] Flexivirx is a great example, but we've got others,
[37:18] we want to take advantage, for example, of the ability
[37:21] to subscribe to data sets.
[37:23] We want to be able to show updates in real time
[37:26] as things are happening throughout the system.
[37:29] And you can't do that, really, if you're using Cloud Functions
[37:33] to retrieve data.
[37:36] So we're very unlikely to utilize Cloud Functions
[37:40] to retrieve data in most cases, but we're
[37:42] reasonably likely to use Cloud Functions to update data.
[37:46] And there's a lot of potential reasons
[37:48] you might want to do that.
[37:49] One of those is the security modeling
[37:51] allows you to put that in code and test it.
[37:53] It also means that you can utilize transactional updates.
[37:57] So if I need to update data across multiple locations
[38:00] simultaneously, I can make sure that all those things went
[38:04] in at the same time, that we're in good shape before I consider
[38:07] that a successful update.
[38:09] I can do that if I put it all in a Cloud Function.
[38:11] I can't do that really any other way.
[38:12] But there's other approaches.
[38:17] So one of the ways that I might do something in some cases
[38:20] is the UI, the front-end client, will update, I don't know,
[38:26] like a marker record.
[38:27] I want to do this thing.
[38:29] And then a function trigger will pick that up
[38:32] and then do the actual work of putting things
[38:36] where they need to go.
[38:38] And you can then have very different rules
[38:42] around what is that queue of actions
[38:46] that I need to perform that can be
[38:48] very different from other things.
[38:50] You could also utilize a message queue directly.
[38:53] It's usually easier just to write that
[38:54] to a location in a database.
[38:57] Then do triggers.
[38:59] Triggers behind the scenes provide some advantages,
[39:03] especially if it's fairly sophisticated.
[39:06] Individual pieces can happen very quickly.
[39:08] You have replayability.
[39:10] You end up with being able to potentially do
[39:15] much larger jobs without the user
[39:17] having to be stuck sitting around waiting
[39:19] for that to happen.
[39:21] There's a lot of cases where you can just
[39:23] do things behind the scenes.
[39:24] The user doesn't care.
[39:25] One example of this is in FlexiPark.
[39:28] When you go to check into a lot, one of the things
[39:32] we let you do is take a photo of your car
[39:35] to register your vehicle.
[39:38] So we'll upload that photo in real time
[39:40] and just move on about--
[39:42] you continue checking in.
[39:44] What we're doing behind the scenes,
[39:46] though, is as soon as that photo hits the storage bucket,
[39:49] we're sending it out to a third-party service
[39:52] to do image detection to extract the make, model, color,
[39:57] license plate, state, and all this metadata
[39:59] about your vehicle.
[40:01] And then it's going to come back and rehydrate that
[40:03] in our system.
[40:06] It happens pretty quickly.
[40:07] It's-- on a bad day, it might take a minute or two
[40:11] for that full-round trip to happen.
[40:13] But that's fine, because by the time
[40:16] you've finished checking in and paying and walking away,
[40:20] we have that data now.
[40:22] And so within a couple of minutes,
[40:24] there's plenty of latitude for an enforcement person
[40:28] to come by and check for your vehicle to leave a ticket.
[40:30] And even if for some reason the metadata didn't make it
[40:34] all the way back, we're going to suggest to the enforcer, hey,
[40:38] I didn't find a match for that license plate,
[40:41] but I do have these two vehicles in the lot that
[40:44] don't have license plate information,
[40:45] but they have photos.
[40:46] Can you please visually inspect and make sure
[40:48] that it's not one of these?
[40:50] Yeah, that's a fantastic backup.
[40:51] Right.
[40:52] Just the manual, easy.
[40:53] Yeah, that's cool.
[40:55] I'm curious, when we talk about triggers and different ways
[40:58] to call, we were talking about that API middleware
[41:01] a little bit.
[41:03] So if you were to write that-- so let's just
[41:07] give a Next.js example, right?
[41:10] You're using the admin SDK within Next.js functions,
[41:13] so you can call them Cloud Functions,
[41:15] whatever you want to call them, in their API escape.
[41:19] Typically, you're using a service account
[41:22] and some server-side keys.
[41:25] Those are not to be exposed because they'll open up
[41:27] the entire application.
[41:29] Do you like seeing that style of, from your application,
[41:35] calling into that type of serverless API call,
[41:39] and then you handle all the admin?
[41:41] Or do you like how Firebase has their own callable functions,
[41:47] and that still utilizes the security
[41:50] that you've already set up?
[41:52] Does that make sense, how I'm asking it?
[41:53] Yeah.
[41:54] It depends on the type of function you're running,
[41:57] but 99% of the time, I like the callable functions
[42:01] because, effectively, if I'm doing it as an API,
[42:05] I effectively want to run that function code
[42:09] within the context of the user who was triggering the function.
[42:12] And so for API types of functions,
[42:18] I want that user's information to come in,
[42:21] and I'm going to verify in the code
[42:24] that they are who they say they are, what's going on.
[42:26] And Firebase takes care of a lot of that initial load for you,
[42:31] validating the token and everything.
[42:32] And then I can look at what are their permissions
[42:36] within my system based upon their permission data,
[42:39] however we've chosen to store that,
[42:41] and make sure that the changes that I'm about to make
[42:45] or the data I'm about to return falls within their rights.
[42:49] And so for that type of function,
[42:53] that's how I want to do it.
[42:54] There are maybe some exceptions, but I generally
[43:00] don't utilize API type of functions for things
[43:06] that I would utilize more of a service account for.
[43:10] What I find myself doing a lot more these days
[43:13] within the Firebase ecosystem is actually
[43:17] to create schedulable functions.
[43:21] Sure.
[43:22] So the reason I'll do that-- so let's say for the sake
[43:25] of argument, because this is something that happens a lot,
[43:27] from a developer administration standpoint,
[43:30] I need to be able to ensure data integrity of something.
[43:33] So I'm going to create this function that I can run that
[43:37] is going to synchronize data or keep things up to date
[43:41] or duplicate or whatever I've got
[43:43] to do to keep things in a really good, clean state.
[43:46] And I'm going to write that in a way that is idempotent.
[43:48] So I can run it as many times as I want,
[43:50] and it's going to continue producing
[43:52] the same correct result on the same data.
[43:55] And then I'm going to put it in a schedulable function,
[43:57] because within the web console that I have access
[44:02] to through Google Cloud, I can very easily click a button
[44:05] and run that function any time I want.
[44:08] But I can also have it run on a schedule.
[44:10] So maybe I want to make sure that once a month
[44:12] or once a week that my data is in good shape
[44:15] and that nothing's gotten out of sync.
[44:16] I can just schedule it to run that often,
[44:19] and then I can kick it off myself whenever I want.
[44:21] So for that type of work, I tend to do that type of function,
[44:27] because if I have to do it once, I'm
[44:30] probably going to need to be able to run it on demand.
[44:33] I generally go that route more than kind of baking it
[44:41] into the application.
[44:42] If it really needs to be built into an admin console
[44:45] or something, then I might possibly
[44:47] go the route of having an admin API do the work.
[44:51] But more than likely, what I'll do instead
[44:54] is actually have an audit log that
[44:56] lives inside of, let's say, Firestore,
[44:58] where the administrative user is going to say,
[45:01] I need to be able to run this task.
[45:03] They're going to submit an entry request into the audit log
[45:06] so that I know who requested it when, what they were asking for.
[45:09] And then I'm going to have a trigger,
[45:11] like a database trigger that's going to respond to that request
[45:14] and then go do the work.
[45:15] And it's going to use the service function automatically,
[45:17] because that's the way Firebase works.
[45:19] And I'm not going to do that through an API call,
[45:22] because I need to have that audit log anyway.
[45:26] I think it's super important for security purposes.
[45:28] So why would I then turn around?
[45:30] I'm going to write the record, and then I'm going to-- no.
[45:33] Rather than calling the API and having the API write the audit
[45:36] record, I'm going to write the audit record directly
[45:39] and then use a Cloud Function trigger to do the work.
[45:42] And it's a reversal of how a lot of times we think about things.
[45:45] Totally.
[45:46] Is that like a Pub/Sub function that you kind of fire off to?
[45:50] Yeah, you can do it as a Pub/Sub.
[45:52] You can do it as just a database update trigger,
[45:54] like a create trigger.
[45:55] So you created something in this audit log.
[45:57] Now I'm going to go do the work that you just told me to do.
[46:00] That's great.
[46:02] What else am I missing around the kind of security rules
[46:07] landscape?
[46:08] I know there's always kind of a lot
[46:10] to just kind of dive in anywhere.
[46:12] But is there any highlights that you would pull out?

46:15 - Recent Improvements in Firebase Storage Rules

[46:15] I would say one big highlight to call out
[46:18] is something that is--
[46:20] it's been around for a while now,
[46:22] but I'm still not sure that it's well understood.
[46:25] And that is that you can write rules against the storage
[46:30] bucket that utilize data in Firestore.
[46:34] So for example, if you have like an access control
[46:37] list or a role-based authentication
[46:39] structure in your data in your Firestore database,
[46:42] you can actually utilize that to provide security
[46:46] to access on the storage bucket.
[46:48] That didn't used to be true.
[46:51] And so what it meant is that you had
[46:52] to jump through a lot of hoops to actually lock down
[46:56] files in the storage bucket.
[46:59] Whereas now, I can write very similar types of rules
[47:03] in the storage bucket to what I would write in Firestore
[47:06] for locking those things down.
[47:08] I can look up and say, does this user have this role?
[47:11] Or does this user with this role have this permission?
[47:14] And then if so, cool, we're going to let them do it.
[47:17] I couldn't do that before.
[47:18] I had to jump through a lot of hoops.
[47:20] You had to either pass--
[47:22] you had to modify the authentication token
[47:26] to include information that those rules could read.
[47:30] You had to potentially utilize Cloud Functions
[47:35] to do some of the access to the storage bucket
[47:38] directly because it was the only way to do it.
[47:40] One of the techniques that we used for a time
[47:43] is when a user was uploading an image,
[47:47] they would upload an image inside of a folder
[47:49] that contained their UID.
[47:51] And so only they would be able to write there.
[47:54] And then we would have a Cloud Function that would then
[47:57] relocate that image to the expected location upon update
[48:03] so that it would end up in the right spot
[48:05] so that you could write rules around.
[48:06] So we did all kinds of jumping through hoops
[48:08] because that really isn't necessary anymore.
[48:11] And I have a blog post on the Firebase Storage Rules
[48:15] utilizing the Firebase data.
[48:17] And it's been a great improvement.
[48:20] Simplified a lot of our code.
[48:22] That's fantastic.
[48:23] I'll have to grab the link for you.
[48:24] I'll put it out in our blog post that comes out for this episode.
[48:28] Perfect.
[48:29] Cool.
[48:30] Sweet.
[48:31] Well, I think with that, we're probably
[48:33] going to jump over to our perfect picks.

48:37 - Conclusion and Perfect Picks

[48:37] Just to kind of get this one out of the way
[48:39] because it's been on my mind, we're actually recording
[48:42] this episode a little early.
[48:43] So we're kind of in Elite 8 zone right now.
[48:47] And I've been watching a lot of basketball.
[48:49] I actually was able--
[48:50] I was visiting a friend in Detroit.
[48:52] And I was like, man, I could actually make a game.
[48:55] So I went to the Purdue game where they won.
[48:58] It's been an incredible season.
[49:00] And it got me like, oh, I want to watch the last dance again.
[49:03] And so I kind of have been watching this each night just
[49:07] to kind of feel that, for me growing up,
[49:10] this was a huge part of--
[49:12] my love for basketball was kind of on the NBA side of things,
[49:17] not necessarily college.
[49:18] College kind of came later for me.
[49:20] So love this show.
[49:22] If you haven't watched it, it's all about the last winning
[49:26] season that the Bulls had with Jordan and Pippen
[49:29] and all those guys.
[49:30] So a lot of journey on the way up to that.
[49:33] So very, very fun Netflix show, if you
[49:37] haven't seen it.
[49:38] All right, Michael.
[49:39] It was truly an amazing, amazing time.
[49:41] Like, I'm not a huge sports fan, but I was then.
[49:45] The way that Michael was able to grow that entire--
[49:49] like, the NBA owes him so much more than we ever
[49:52] even give him credit for.
[49:53] We can easily just say, oh, he was the greatest basketball
[49:56] player ever.
[49:57] There's so much more to it than that.
[49:59] It's unbelievable.
[50:02] Sorry, yeah, so yours is probably
[50:04] a little more fun for most of our people
[50:07] because they're not as sporty.
[50:10] Yeah, I ran into Costco the other day,
[50:14] and these were just sitting there walking in.
[50:16] And I had just been thinking, I want
[50:18] to buy some flowers for my partner.
[50:19] And those were right there.
[50:20] I'm like, what are the best flowers?
[50:22] These flowers are forever, so totally.
[50:26] That's always been my wise request, too.
[50:28] Like, don't buy me flowers.
[50:29] And they'll be like, why didn't you buy me flowers?
[50:32] I can't win.
[50:34] Like, these would be amazing and perfect.
[50:37] It's such a cool set.
[50:38] LEGO has, like, the price on some of this stuff.
[50:41] So I actually bought my wife and a friend of ours
[50:45] the office LEGO set right when they first came out
[50:50] because they're obsessed with the office.
[50:52] And the details on those things are unbelievable.
[50:56] Like, the little coffee-- or the soup pot
[51:00] that Kevin spills in there, like, it's ridiculous.
[51:03] It's awesome.
[51:05] I feel like LEGO has just branched out.
[51:07] There's this whole spectrum of LEGO
[51:09] that is targeted at adults now.
[51:11] And they are just amazing, so cool.
[51:14] Like, I feel like they started with the partnerships, which
[51:17] basically saved LEGO, essentially.
[51:19] And they started with, like, all the, like, nerd stuff,
[51:22] like Star Wars and things like that.
[51:24] And now it's just, like, so many different things in there.
[51:26] It's unbelievable.
[51:28] They understood their audience.
[51:30] Yes, exactly.
[51:32] Maybe we get some Firebase logo, or Firebase LEGO.
[51:36] One of the cool things about LEGO, too,
[51:38] is that they run serverless.
[51:42] Oh, really?
[51:43] Nice.
[51:43] Yeah, it's super cool.
[51:45] So I've got to meet a number of the engineers from LEGO
[51:48] over the years, and they just do cool stuff over there.
[51:51] That's really cool.
[51:52] Yeah, I love even their robotics side of the house over there.
[51:56] I know that's kind of a different realm than this,
[51:59] but you can build amazing things with their robotics stuff.
[52:03] Yeah, yeah, for sure.
[52:06] Well, Michael, thanks so much for joining me.
[52:08] I'm doing a fun month of Firebase
[52:11] and learning all kinds of things,
[52:13] instead of bouncing all over the place.
[52:15] So if you have any friends, please send them my way.
[52:19] We'll get some more recorded stuff.
[52:22] In the meantime, everyone, enjoy.
[52:24] And thanks again, Michael.
[52:25] We'll see you soon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment