This past week I was working to migrate a site from our old CMS to our new CMS. It's a daunting, partly manual process, especially for large sites. But it's one we're happy to do to get our customers into a superior content management system. In this case, I needed to secure nearly all of the pages for a site by utilizing their external custom app to handle the authentication. Marketpath CMS simply performs checks to validate that login.
I won't discuss the auth validation here. That wasn't the issue. The issue was I needed to redirect the user to the custom app's login page if they weren't logged in. Seems simple enough - just add a meta refresh tag with the login url. Easy peasy, except it wasn't. I can't return any of the page content because anyone can fetch the url contents and display them without authenticating.
Instead, I need to wrap all the content in a big if statement (yes, there are big if statements and little if statements - it's a thing) and if not authorized, return the minimal html so the meta refresh redirects the user to the login page.
Up to this point, all of our new CMS sites used a partial header template and a partial footer template. These were included and in the page template. A simple example is below.
header partial template
<!DOCTYPE html> <html lang="en"> <head> <title>My Page</title> </head> <body> <div class="header">....</div> <div class="main-content">
page template
{% include "header" %} <div class="left"> ...... </div> <div class="right"> ...... </div> {% include "footer" %}
footer partial template
</div> <div class="footer">....</div> </body> </html>
The biggest issue with this method is that, with liquid, I can't start an if statement in the header and end it in the footer. if statements must be completed within their own template.
Instead of including a header template and a footer template I can make a master page template and extend it. So the above code then becomes two templates instead of three.
master template (partial template)
<!DOCTYPE html> <html lang="en"> <head> <title>My Page</title> </head> <body> <div class="header">....</div> {% block main_content %} <div class="main-content"> <div class="left"> ...... </div> <div class="right"> ...... </div> </div> {% endblock %} <div class="footer">....</div> </body> </html>
specific page template
{% extends "master template" %} {% block main_content %} <div class="full-column"> ...... </div> </div> {% endblock %}
In this example, the specific page template only provides those blocks that are defined by the master template. Any other top-level liquid tags will throw an error. You can only have extends and block tags in a template that extends another.
By building my templates this way I am reducing my template load by one and allowing myself to wrap all the content in the big if statement. See below for an example.
master template with authentication logic
{% assign is_authenticated = ([AUTH LOGIC GOES HERE]) %} {% if is_authenticated %} <!DOCTYPE html> <html lang="en"> <head> <title>My Page</title> </head> <body> <div class="header">....</div> {% block main_content %} <div class="main-content"> <div class="left"> ...... </div> <div class="right"> ...... </div> </div> {% endblock %} <div class="footer">....</div> </body> </html> {% endif %} {% unless is_authenticated %}<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="refresh" content="0; url=https://customerloginapp.com/" /> </head> <body> Redirecting...</body> </html> {% endunless %}
There are two things happening here. First, I'm excluding my auth validation logic. That will be for a future post. 2nd I am using a single if statement and then an unless statement. While working with this code (and beating my head against a wall) I found a bug with having blocks inside an if/else block. Get rid of the else and use unless and it works. It's weird, I know. And when I say I found the bug, I really mean our senior product developer, Levi Carter, found it. He also discovered this master template capability. Kudos, Levi. Kudos.
Finding the master template feature was a great addition to our toolbox for developing complex websites. This is definitely one we'll continue to use in the future.