Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: wordpress

  • Still Not Using Plugins for Security

    Still Not Using Plugins for Security

    Seven years, and my answer to 'do I need a security plugin' is the same.

    Nope.

    What is a Security Plugin?

    A security plugin is not a plugin like 'brute force protect' or 'limit login attempts.'

    A security plugin is like Better WP Security or WordFence or a hundred other plugins that promise to scan your site and let you know what's changed.

    This is not to say that first set of plugins aren't there to make you 'safer,' it's that those are single use, targeted plugins that address a single issue. Limiting login attempts prevents someone from trying the same attack over and over and over until they get in.

    By contrast, all-in-one security plugins try to do everything. They scan your code, your data, and your site. They look for all the possible attack vectors and they try to plugin them.

    What Makes That Secure?

    That's the question I ask people. If a plugin adds in 2-factor authentication, I ask them what it does for them? Password expirations, captchas, file compares etc. Those are all good things, individually, but are they applicable for all people? What, specifically, about those things makes you more secure or not?

    Now. Before you get all shirty with me, I am well aware of what all of those things are good for. With the exception of captchas (which are not accessibility friendly, please stop using them), all of those things make a lot of sense. You expire passwords and, one hopes, require strong passwords to make it harder to break in. But if you have a 2FA setup, do you need to require rotating passwords?

    It’s All About Thinking

    Security plugins stop people from thinking about what's going on.

    I've seen it time and again, people install a plugin that 'makes them safe,' follow the bare minimum of requirements, and then install whatever they want without thinking about it, leave registrations open, and oops, get hacked.

    This is not to say that security plugins don't prevent some of that from happening, but they're often an 'after the fact' solution. That is, usually a security plugin doesn't know to block X until X has been exploited. That's kind of the nature of the beast, though, and why WordPress and many other CMS developers don't release full details on security fixes until they've been out there for a while. They want to give people a chance to upgrade before saying "Hey, y'all who didn't are super vulnerable."

    It’s Also About Speed

    Security plugins also have a tendency to make your site slower. This usually comes up when people have turned on everything that comes with a security plugin. Which goes right back to my point about thinking. The user doesn't think, because they're not yet educated, about the impact of the code on their site.

    To put it simply, the more things you ask WordPress to do before it can load a page, the slower it will be to load a page.

    Pretty cut and dried, right?

    What’s My Answer?

    I don't call this the 'right' answer or even the best one. Not everyone has access to my resources after all, so it's not fair to say "Hire Mika to think for you!" But to me, the best answer is to use the resources you have intelligently.

    Firewalls, from a server side, are all but a requirement to me. If your web host doesn't have one, and most at least have ModSecurity, get a new web host. If you disabled it on your site because a random plugin doesn't work with it, delete the plugin and turn it back on. If you can't move to a new host, look into firewalls like Incapsula or Sucuri. Put something between users and data.

    Site Scanning is a great tool, but don't run it on WordPress. A great example of smart security scanning is VaultPress. It's a remote service that has a copy of all your files and it scans the copy, not your site, for issues. There are other services you can use that scan your site without affecting traffic. Again, web hosts often have tools for this.

    Be Aware of what's going on. Don't just let security be a black box. Make sure you know what kinds of attacks are common on your site. If you're hit by a DDoS, for example, where they're just hammering your site to take it down, a 2FA plugin will not help. If they're trying to log in all the time, a scanner is probably not what you need.

    Lock It Down. If you don't need it, don't use it. If you don't need it on, turn it off. Update regularly. Don't install everything under the sun. 

    Don’t Buy Into FUD

    This is a tricky balance. On the one hand, I want to say 'don't panic if your favourite security plugin of choice tells you everything doomed!' Remember, they're trying to sell you things. But on the other … don't think everything's fine and dandy.

    It's not a simple solution. You have to simultaneously be aware of problems and not overwhelmed by them. You have to learn how to care about which ones are important to you and which are not.

    In a word, you have to think.

    And there is no plugin on the planet that can think for you.

  • The Purpose of a Case Study

    The Purpose of a Case Study

    Back in early December I gave a talk at WordCamp US about a website I built with Tracy. The talk was titled “Lesbians, Damn Lesbians, and Statistics.” You can watch it here:

    Of all the talks I’ve given, I feel it was the least WordPressy of them all. That is, while I did talk about WordPress and why we made choices that we did, and how they relate to the data design, it wasn’t very code heavy. It was, instead, a case study in how and why and what.

    What

    A case study talk is complicated because you have to address what the topic is beyond WordPress. When you start with WordPress, and you’re at a WordPress convention, you don’t have to lay the groundwork. You can jump in and talk about custom post types and taxonomies. At a WordCamp, everyone knows about WordPress, or at least enough to skip over the basics.

    On the other hand, your case study starts by explaining what the reason was that you built the site in the first place. What’s the purpose of the site and what’s the relation to WordPress. You start with the narrative of “This is my story.” And you have to do it fast because next is the why!

    Why

    Once you have explained what the site is about, you have to explain why WordPress. When you’re doing a normal talk about WordPress things, you skip right over this. Everyone knows why WordPress. Because WordPress! But many times we ask ourselves “Is WordPress the best tool for this job?” We ask “Is it the right tool?” So in a case study, you have to build up your case and explain why.

    This is hard, because you already jumped through those hoops to explain to yourself (and any business partners you’re working with) the rationale. Distilling all of that into a third of your talk, which means maybe ten minutes, is not easy. You summarize, you skip over things, and you still have to hit the main points or people won’t be able to make the connections for the next section.

    How

    Finally you have to explain how you did this. If people don’t understand what you did and why, the how becomes meaningless. This is because the brunt of your talk takes place here. This is the real WordPressy stuff, where you talk about how the what and why came together to be this thing. If people can understand the enormity of the data, they can conceptualize your logic.

    If you’ve built everything up before, people will understand “Oh, she couldn’t make death a taxonomy because the overlap would cause problems and become unwieldy.” They’ll follow you when you explain about faceting searches and moving data.

    Because

    The purpose of all this is to draw people in with a cohesive story that puts the code and the concept together. People remember songs because of the rhythm and pattern. They will remember your case study because of the story. We remember stories.

    The purpose of your case study is to tell a good story that people remember and that connects them to your topic and your code.

  • Zap a Daily Tweet

    Zap a Daily Tweet

    Last week I told you how I made a random post of a day. Well, now I want to Tweet that post once a day.

    Now there are a lot (a lot) of possibilities to handle something like that in WordPress, and a lot of plugins that purport to Tweet old posts. The problem with all of them was that they used WordPress.

    There's nothing wrong with WordPress

    Obviously. But at the same time, asking WP to do 'things' that aren't it's business, like Tweeting random posts, is not a great idea. WordPress is the right tool for some jobs, but not all jobs, after all.

    What is WordPress' job is generating a random post and setting a tracker (transient) to store for a day. And it's also WordPress' job to output that data how I want in a JSON format.

    The rest, we turn to a service. Zapier.

    A Service?

    Like many WordPressers, I like to roll my own whenever humanly possible. In this case, I could have added an OAuth library and scripted a cron job, but that puts a maintenance burden on me and could slow my site down. Since I have the JSON call, all I need is 'something' to do the following:

    1. Every day, at a specific time, do things
    2. Visit a specific URL and parse the JSON data
    3. Craft a Tweet based on the data in 2

    I dithered and kvetched for days (Monday and Tuesday) before complaining to Otto on Tuesday night. He pointed out he'd written those scripts. On Wednesday, he and I bandied about ideas, and he said I should use IFTTT. Even using IFTTT's Maker code, though, the real tool needed is one that lets me code logically.

    Zapier

    The concept of IFTTT is just "If This, Then That." If one thing is true, then do another. It's very simple logic. Too simple. Because what I needed was "If this, then do that, and tell another that." There wasn't an easy way I could find to do it with IFTTT so I went to the more complicated.

    Example of what the flow looks like - Trigger is every day, action is GET, final action is tweet

    Three steps. Looks like my little three item'd list, doesn't it?

    The first step is obvious. Set a specific time to run the zap. It's a schedule. The second step is just a web hook saying 'Get the data from URL.' And the third step is aware!

    Showing the example of the tweet, with placeholders for the name and URL

    Pretty nice. If you click on the 'add field' box in the message content (upper right), it knows how to grab the variables from the previous steps and insert them. Which is damn cool.

  • Random Post of the Day

    Random Post of the Day

    I wanted to make a random post of the day. In this case, I wanted it to be a random post of one of two custom post types, and I wanted to output it as JSON for a variety of reasons, including future plans. Like tweeting that post.

    I’ll get to that later.

    Overview

    To do this, I have the following moving parts:

    1. The RESTful routes
    2. The random post
    3. The expiration (i.e. each post lasts a day)

    I’m going to skip over how to make a REST API route. I talked about that earlier in 2017 when I explained how I made the Bury Your Queers plugin.

    What’s important here is actually the random post and spitting out the right content.

    Getting a Random Post

    This is cool. WordPress can do this out of the box:

    $args = array( 
    	'post_type'      => 'post_type_characters',
    	'orderby'        => 'rand', 
    	'posts_per_page' =>'1',
    );
    $post = new WP_Query( $args );
    
    while ( $post->have_posts() ) {
    	$post->the_post(); 
    	$id = get_the_ID();
    }
    wp_reset_postdata();
    
    $of_the_day_array = array(
    	'name'   => get_the_title( $id ),
    	'url'    => get_permalink( $id ),
    );
    

    And at that point all you need to do is have the API return the array, and your final output is like this:

    {"name":"Van","url":"http:\/\/lezwatchtv.com\/character\/van\/"}
    

    This is a simplified version of my code, since in actuality I’m juggling a couple post types (shows or characters), and outputting more data (like if the character is dead or alive). It’s sufficient to prove this point.

    Expirations

    Okay. Now here’s the fun part. If you go to your JSON page now, it’ll show you a new character on every page reload, which is absolutely not what we want. We want this to only update once a day, so we can do this via Transients like this:

    if ( false === ( $id = get_transient( 'lwtv_otd_character' ) ) ) {
    	// Grab a random post
    	$args = array( 
    		'post_type'      => 'post_type_characters',
    		'orderby'        => 'rand', 
    		'posts_per_page' =>'1',
    	);
    	$post = new WP_Query( $args );
    	// Do the needful
    	while ( $post->have_posts() ) {
    		$post->the_post();
    		$id = get_the_ID();
    	}
    	wp_reset_postdata();
    	set_transient( 'lwtv_otd_character', $id, DAY_IN_SECONDS );
    }
    

    But.

    Transients kinda suck.

    Expirations 2.0

    Alright. Let’s do this differently. The server this is on has object caching, and it gets flushed every now and then. While it doesn’t matter if the post is re-randomizes in this case, it’s still not a great practice. So let’s use options!

    // Grab the options
    $default = array (
    	'character' => array( 
    		'time'  => strtotime( 'midnight tomorrow' ),
    		'post'  => 'none',
    	),
    	'show'      =>  array( 
    		'time'  => strtotime( 'midnight tomorrow' ),
    		'post'  => 'none',
    	),
    );
    $options = get_option( 'lwtv_otd', $default );
    
    // If there's no ID or the timestamp has past, we need a new ID
    if ( $options[ $type ][ 'post' ] == 'none' || time() >= $options[ $type ][ 'time' ] ) {
    	// Grab a random post
    	$args = array( 
    		'post_type'      => 'post_type_characters',
    		'orderby'        => 'rand', 
    		'posts_per_page' =>'1',
    	);
    	$post = new WP_Query( $args );
    	// Do the needful
    	while ( $post->have_posts() ) {
    		$post->the_post();
    		$id = get_the_ID();
    	}
    	wp_reset_postdata();
    
    	// Update the options
    	$options[ $type ][ 'post' ] = $id;
    	$options[ $type ][ 'time' ] = strtotime( 'midnight tomorrow' );
    	update_option( 'lwtv_otd', $options );
    }
    

    And now you see my $type variable and why it matters. There’s more magic involved in the real world, but it’s not relevant.

  • Hey You Gays Filter

    Hey You Gays Filter

    Are you tired of people always saying ‘guys’ when they’re talking to a mixed gender group of people? I know I am. One weekend I got four (yes four) comments about my code saying “You guys should…” or “Ask the guys who …” and so on.

    All implied I wasn’t the human who wrote the code. Spoiler alert. I was. While I can’t fix the world out there, I do tend to reply with a handy gif:

    Eowyn from Lord of the Rings, pulling off her helm and shouting I AM NO MAN before killing a wraith and saving everyone.

    But I can fix MY site. Since I only need this for comments on my site (I’m in charge of how I write), I can use this:

    add_filter( 'comment_text' , 'hey_you_gays', 11 );
     
    function hey_you_gays( $text ) {
        static $dblq = false;
          if ( false === $dblq )
            $dblq = _x('“', 'opening curly quote');
          return str_replace(
            array( ' guys', '‘guys', $dblq . 'guys', '> guys', '(guys' ),
            array( ' guys', '‘gays', $dblq . 'gays', '> gays', '(gays' ),
          $text );
    }
    

    If you need to use it in titles and post content, steal the code from capital_P_dangit(). After all, that’s what we do.