Module 1 - Introduction
1. Welcome to the course2. Why Go3. Why start and build a blog?4. What about React/Vue/Angular?5. Getting setup and source filesModule 2 - Tech Stack Walkthrough
1. Introduction to Golang Part 12. Introduction to Golang Part 23. Introduction to Golang Part 34. Structuring Golang Applications5. Templating with Templ6. Just enough interactivity with HTMX7. Getting started with postgres8. Servers, routers and endpointsModule 3 - Creating the MVP
1. What are the minimal requirements?2. Doing some initial plumbing3. Embedding static assets4. Creating our first views5. Tailwind & Utility-first CSS6. Styling the Landing Page7. Styling the Article PageModule 4 - Managing Content
1. Choose your own adventure2. Writing in Markdown3. Parsing Markdown to HTML4. Frontmatter and Meta Information5. Making our code examples look nice6. Adding error pagesModule 5 - Adding the Database
1. What is a Migration?2. Our first migration: articles table3. Creating the Database Layer4. Showing the Latest Posts5. Slugs and Human Readable URLsModule 6 - Managing the Blog
1. What are the minimum requirements?2. A new layout approaches3. Introduction to authentication4. Our second migration: Users Table5. Storing passwords securely6. Authenticating users Part One7. Authenticating users Part Two8. Remember me/Forget me9. Managing posts using a hypermedia API - Part One10. Managing posts using a hypermedia API - Part Two11. Managing posts using a hypermedia API - Part Three12. Managing posts using a hypermedia API - Part Four13. Implementing CRUD For Articles - Part One14. Implementing CRUD For Articles - Part Two15. Implementing CRUD For Articles - Part Three16. Implementing CRUD For Articles - Part Four17. Flashing Ourselves/Providing Visual Feedback - Part One18. Flashing Ourselves/Providing Visual Feedback - Part Two19. Flashing Ourselves/Providing Visual Feedback - Part ThreeModule 7 - Adding Subscribers
1. What are the minimum requirements?2. Expanding the database: Tokens & Subscribers3. Creating the token and subscriber models - Part One4. Creating the token and subscriber models - Part Two5. Creating the subscription form6. Saving and verifying subscribers - Part One7. Saving and verifying subscribers - Part Two8. Saving and verifying subscribers - Part Three9. Emails and Clients - Part One10. Emails and Clients - Part Two11. Emails and Clients - Part Three12. Our fifth migration: Tokens Table13. Email validation view14. Email validation tokens15. Sending validation emails with SES16. Making it all come togetherAdding Subscribers
Saving and verifying subscribers - Part Two
Summary
Coming soon.
Transcript
Next step in the happy path is that the user received this email with a valid link that they didn't click, and now we have to handle that. And I'm just going to grab this one more time here, and we're going to call this subscriber email verify. And what we will do when we create the email is we will send them a link that goes to a specific endpoint that has a query param. And that query param is going to be the hash of the token. So we're going to pull out this hash from the query param. We're going to look up any tokens with that hash. We're going to check if that token is valid and has the right scopes. If that is all good, we're going to pull the subscriber from the database. We're going to update them to having an email verified, and then we're going to show our success message saying, like, you are valid, you're verified now, and you can start receiving our newsletter posts. So to begin, we need to pull the hash, and we can do that by calling the query param method on the context here. And we're going to call this hash. Then let's just go up here because we also need to create a transaction for this flow. So this is going to be literally the same as before. Now let's pull the token, say models, get token, pass the data or the arguments here, the hash, and going to return subscription validation failure, right? Subscription subscriber, sorry, email, I can't spell subscriber, subscriber, subscriber email validation failure, there we go. And we also need to provide them with a token. So if everything goes wrong here, we render the form saying, hey, something went wrong, you can request a new token here, right? So that's why we need the CRO's token. Now we can copy paste this. Again, we can find the token, we just return that message. Then we say if token, we're going to use a helper method here, is valid. And token meta scope, right, is not models.scope email application and model, no, token meta scope dot, we have to use resource does not equal models subscriber, right? So if it's not valid, maybe we should actually say or, yeah, we should have or, right? So if the token is not valid, or if the scope is not email replication, or the resource is not our subscriber resource, then again, here, we need to turn our message, the failure message saying, again, request a new token. However, if none of these Boolean statements is returns true, then we are going to pull the subscriber, saying models, get subscriber, and we're going to get subscriber by ID. Pull and we have the token resource ID. One more time. Oh, not almost. We're going to do it again. We have to subscriber, we're going to update. And again, we're going to use a blank statement here for the return value because we actually don't need the subscriber, the updated subscriber anymore. So we're just going to say blank here. And we are going to call models, update subscriber, pass the payload, and we need to say the ID is the subscriber dot, oh, subscriber, there we go. And email, we could technically create a specific method for this that says validate subscriber, which potentially also be valid, but we're just going to use a generic update here. So that's why we also need to pull the subscriber so we can, we don't overwrite the email to an empty string. All right, go return the failure if something goes wrong. Finally, and this is why we needed to use a transaction, we need to delete their token. So we're going to say delete token. And we had the token.id. Again, and I actually think this is the last time, right? No, we also need to commit. So let's just grab the commit here and return this error message. Finally, we can return views, subscriber email, this is a success, render, and pass our render args. What is it complaining about here? So, of course, we need this. There we go. So this is how our email verification or verify handler is going to look like. We grab the hash from the query param, we pull out the token, we validate that it's valid, we pull the subscriber, we update the subscriber, finally we delete the token, commit the results and return a success message to the user.