Categories
Personal

Hell Of A Year

The post I wrote at the beginning of the pandemic ended with “But we’re going to be alright.”

It sounded half-hearted then, and I was considering whether to put it in or not. Still, in the end, I decided that the purpose of the post was to reduce my anxiety, so I kept it.

Since then, I tried to write several posts just as a memory checkpoint but could never finish. They’re still in the drafts but unlikely to be seen by anyone but me.

Back then (a year ago), I chose to focus on the positive outcomes that the pandemic may produce. Now it’s time to check how it unfolded in reality.

Remote Work

This was a no-brainer, obvious thing to me. I worked remotely for at least half of my career and always thought that remote work share will just slowly inch up. The pandemic significantly accelerated the process. 

However, I failed to see how many will struggle to work from home. Some couldn’t focus because it was too big of an adjustment for them. Others would struggle because they live in smaller places where there are just too many people around to be productive. Top it up with children not being in school to make it extra hard to stay productive. 

Each of us probably had a video call where someone’s kid walks in, or a spouse makes a guest appearance in a washed-up hoodie and sweatpants.

Still, I think this is the most favorable consequence of the pandemic. It’s not for everyone, but more people will be able to work remotely should they wish to do so. 

Remote Learning

It didn’t work. In fact, this one is a total shit-show. The change was so drastic and abrupt, it was not a pleasant experience. My child is not in school yet, so I was/is merely a spectator of others’ struggles on this one. I saw that kids couldn’t focus, parents couldn’t work, teachers hadn’t had curriculums prepared, everyone was scrambling.

Then, of course, there’s inequality. I failed to see how for some kids, the school means a meal, and not going to school may mean they will be hungry that day. If one’s in that situation, chances are they don’t have a laptop to do the remote learning either.

But even the kids who are fortunate to grow up in a well-off household are struggling. Turns out, having peers and teachers close-by plays an essential part in the overall learning process. Some children don’t mind, some are thriving, and many are struggling.

There are programs to provide meals to students and the necessary technology for e-learning. But those are not real solutions, more like mitigation.

Carbon Footprint

Yes, carbon dioxide emissions had dipped, but it likely won’t have a pronounced long-term impact.

Global carbon dioxide emissions fell by 2.6 billion metric tons in 2020, to 34 billion metric tons — a projected decrease that puts it at about 7% below 2019 levels, carbon-tracking research shows.

Regardless, one year of nose-diving emissions isn’t enough to make a serious long-term impact, Le Quéré and her coauthors wrote. To meet the Paris climate targets, the U.S. and the rest of the world will need to cut their emissions by about 1 billion to 2 billion metric tons per year — near-pandemic-level reductions — for every year throughout the 2020s.

https://news.yahoo.com/covid-19-helped-slash-2020s-160017912.html

Yet, it may as well be the global oil demand has peaked and will only decline from now on.

Healthcare And Worker Rights (U.S. Specific)

Hahahahaha, nope, that totally didn’t happen. 

The average cost of hospital care for COVID-19 patients without insurance or who receive out-of-network care varies greatly by age – from $51,389 for patients between 21- and 40-years-old to $78,569 for patients between 41 and 60 years old, according to updated cost analysis data from FAIR Health.

https://www.healthcarefinancenews.com/news/average-cost-hospital-care-covid-19-ranges-51000-78000-based-age

Really it’s hysterical (not in a funny way, of course). Imagine almost dying and then being hit with a bill like that. For some, it’s gruesome reality.

Personal Hygiene

I was so-so-so wrong on this one. I couldn’t imagine that masks will become such a polarizing issue. I thought (and think to this day) it’s such a simple, effortless thing to do. Yet, some people would be ready for a physical confrontation to not wear a mask, and others would take it to the streets. 

Food Waste

Honestly, hadn’t paid any attention to it on a global scale. We certainly got better around not wasting food at home, but I’d be lying if I said it doesn’t happen at all.

Personally

Juxtaposed to global misery, we’re doing just fine. We never got infected (at least to our knowledge), did 3 tests total, all were negative, so even if we had it, we were asymptomatic. I’m going to do an antibody test just to be sure the next week, when I’ll finally go to my annual medical exam (the last one was in 2019).

It was rough. It still is. During the initial lockdown, mental health took a hit. Mostly it was around the fear of the unknown and crushing apathy. Apathy is the reason why I never finished any of those previous posts.

Since then, the fear of the unknown got replaced by the fear of the known. That’s marginally better for me because when I fear something known, I can take steps to avoid it, thus maintaining an illusion of control.

Enter “risk budget calculation”! Something I get to do every day, so much, so it’s like a background process now. Is this thing I want/need to do really worth the risk of doing it? How big is the reward for me to considering taking this risk? 

There’s not a single day when I’m not grateful for what I have. I recognized that I live a privileged life, I realized how lucky I am. 

What’s next?

Since the beginning, I put all my faith in science, humans – not so much.

The science came through. We got efficacious vaccines, and everyone who wishes to get vaccinated will get to do it soon. 

Humans, though, made it so much worse than it could’ve and should’ve been. I’m looking at some Asian countries which crushed it and can’t help but shake my head at the total self-inflicted mess we have here in the U.S. or back home.

Many people could’ve been alive today if more of us put the public good first. Instead, freedom to do the wrong thing prevailed. Unsurprisingly to me, really. Humankind likes to think of it as the pinnacle of creation, where in reality, we’re just a bunch of evolved primates driven by the same primal instincts.

I’m optimistic the worst is over, but I’m not getting my hopes too high.

Categories
Personal

When The Dust Settles: Focusing On Positive Changes

If you’re anything like me, you’re probably tired, and a bit scared about the COVID-19 pandemic. The situation evolves quickly and dramatically, but I think we can all agree that the writing is on the wall: either us or our loved ones will likely contract the virus (current estimates are 20% to 70% of the world population will get it). Most of us will be okay, but some will die. 

Confirmed cases keep growing exponentially. At the moment of this writing, there are 145,637 cases with 72,529 recoveries and 5,436 deaths (according to Worldometer), 91% are in Mild сondition. 

So, yeah, it’s exhausting to keep up with the coronavirus news. It’s taking a mental toll: even if you think you’re not at risk of becoming “the Severe case,” you have older and immunocompromised people in your life. Unless you’re a psychopath, you’re anxious about them right now.

I found myself in a feedback loop. I scroll through the Twitter feed, see bad news, get anxious about it, go do something else. Still, my mind is preoccupied, so I go back to Twitter to read more scary news stories. Ad infinitum.

My usual coping mechanism is humor: crack a couple of jokes, make some memes, feel a bit better. This time it doesn’t work, it’s just too much. So I decided to try something else, specifically, a thought exercise. I asked myself: “what positive changes we, as a species, may create in the aftermath of the pandemic?” 

Change Is In The Air

Historically, tough times drastically change the way of life. Be it a world war or a deadly pandemic, humanity reacts, responds, and adapts. I feel like we’re in the moment that can cause profound change.

The following is a speculation based on the feelings and thoughts I have. It’s not scientific or backed by any data, but I really wish some of it becomes a reality.

Remote Work

Out of the few positive changes I came up with so far, this one seems the most realistic. As the pandemic has already shown, going to the office is absolutely not required for many modern-day jobs. All of a sudden, huge corporations don’t have issues with their employees working remotely. 

Remote work will enter the mainstream, it no longer will be a gimmick reserved for tech companies and freelancers.

Remote Learning

Just as with the remote work, people will realize that going to a school is not a hard requirement. It’s already a thing, but it’ll become more pronounced.

Carbon Footprint

This one stems from the previous two (and the travel industry having near-death experience). As more people work and learn from home, they will use their cars less. This will help with traffic congestion in the bigger cities and give our planet some much-needed breathing space. 

Healthcare And Worker Rights (US Specific)

My hope is that the currently unfolding situation will put inadequacies of the current system in a very intense spotlight. Thus, shifting the public opinion from “universal healthcare is communism” to “I can’t believe we were dealing with this for-profit insurance nonsense for such a long time.”

Another positive might be the guaranteed paid medical leave for every employee. No one has to go to work when they’re sick. It’s a straightforward concept, and the lack of grasp on it in the US is dumbfounding.

Personal Hygiene

For the last couple of months, I’ve been becoming increasingly aware of people coughing around me, and I watched them closely. Many don’t cover their mouth at all, and some do it wrong. 

I must admit, until recently, I have never washed my hands properly. I did it, but half-assed the whole thing: missed spots and rarely (if ever) did it for more than 10 seconds. If my parents ever taught me how to do it right, I totally forgot. 

I hope we collectively learn how to wash our hands thoroughly and cover our coughs or sneezes. This will help prevent or mitigate local/global outbreaks of various diseases.

Food Waste

My granda used to discipline me each time when I was playing with food. As a child, I didn’t understand it. I found it quite entertaining to kick a bread bun or throw an apple. She’d become furious and said something like, “You have to respect the food! Bread is not a toy!” Those memories came back to me as I was watching people panic-shopping on the Internet and, two weeks later, in real life. 

We toss an astonishing amount of food in the garbage. I hope this crisis will make us more mindful of what we eat and what we throw out.

Conclusion

Only time will tell how much of the above will become a reality and how much will stay wishful thinking (or a pipe dream, depending on one’s perspective).

I know one thing. The harder we’ll get hit in the following weeks, months, and maybe years (see the Spanish Flu), the likelier the changes will stick. If one cuts a finger with a knife, they might learn how to properly hold it; losing a finger will have a lasting effect for the rest of their life. 

But we’re going to be alright.

Categories
Code

How to lock down or disable WordPress REST API Endpoints.

Script kiddies hate this one little trick!

WordPress REST API is a powerful tool. However, with great power comes great responsibility. Such as, for example, to not accidentally disclose information about your users. Yet, this is exactly what happens when you hit /wp/v2/users endpoint. You can view users or you can view specific user information by adding the id argument. E.g. /wp/v2/users/31337

I can respect WordPress’ stance (as I understand it). “It’s the Web, people will access your site, WordPress is a blogging software”. But I don’t have to agree with it. IMO default permissions are too open for many cases.

There are several ways of restricting access to REST endpoints. I’m going to cover some of them.

TL;DR

Note on cookie-based auth security.

REST API requires requests to be signed with a nonce to mitigate the possibility of a CSRF attack: if someone steals your user’s cookies, they won’t be able to pose as that user without that nonce. You can use capability checks (e.g., current_user_can in all of the approaches listed below, but, in case you see unintended results in your testing, the chances are that you may have forgotten to pass the correct nonce to the request. Be sure to check the REST API cookbook for more details on cookie-based auth.

The hardcore way: rest_endpoints

You may have seen advice to use the rest_endpoints filter. I think it’s not a good option for the majority of the cases. Here’s an example:

// Nuclear option: disable all endpoints
add_filter( 'rest_endpoints', function( $endpoints ) {
	// No REST for the restless
	$endpoints = [];
	return $endpoints;
} );

There, easy, right? All endpoints are gone, and we’re entirely “safe.” The only problem? Now you might have a broken site. Both Core and User-land code (plugins) use REST API extensively, so filtering out endpoints like that can break things. Depending on what was filtered, it can blow up either spectacularly (try the above with Gutenberg on) or subtly.

My issue with that approach is that the filter is unwieldy because it’s a huge array with routes as keys. From the docs:

(array) The available endpoints. An array of matching regex patterns, each mapped to an array of callbacks for the endpoint. These take the format '/path/regex' => array( $callback, $bitmask ) or '/path/regex' => array( array( $callback, $bitmask ).

https://developer.wordpress.org/reference/hooks/rest_endpoints/#parameters

Now you either have to iterate over the array to figure out which endpoints to remove or call unset on specific ones:

// Remove a specific or several endpoints
add_filter( 'rest_endpoints', function( $endpoints ) {
	// Unset a specific endpoint
	unset( $endpoints['/wp/v2/users/(?P<id>[\\d]+)'] );
	// or iterate and figure out which ones to remove
	foreach( $endpoints as $route => $handler ) {
		// somehow decide this endpoint needs to be removed
	}

	return $endpoints;
} );

If you want to use a nuclear option to “disable” REST API, this is your jam. Removing endpoints using this approach results in a 404 error:

{
  "code": "rest_no_route",
  "message": "No route was found matching the URL and request method",
  "data": {
    "status": 404
  }
}

More balanced approach: rest_authentication_errors

I think this method, while not without drawbacks, is preferable.

Filters REST authentication errors.

WP_Error instance can be returned if an error occurs, and this should match the format used by API methods internally (that is, the status data should be used). A callback can return true to indicate that the authentication method was used, and it succeeded.

https://developer.wordpress.org/reference/hooks/rest_authentication_errors/

NB: You have to be mindful about the return value in this filter, returning true effectively disables the nonce check in the Core’s rest_cookie_check_errors, thus leaving your site vulnerable.

But there are situations where you wouldn’t care as much about the nonce check. Suppose you want to bump the default permissions for all endpoints to be at least edit_posts except for pages endpoint:

// More balanced approach
add_filter( 'rest_authentication_errors', function( $maybe_error ) {
	// Only allow authors and up, except for the pages endpoint
	if ( ! ( current_user_can( 'edit_posts' ) || false !== stripos( $_SERVER['REQUEST_URI'], 'wp/v2/pages' ) ) ) {
		return new \WP_Error(
			'rest_auth_required',
			'No REST for the restless!',
			['status' => 401 ] 
		);
	}

	// Pass through
	return $maybe_error;
} );

Let’s unpack what’s happening here: we’re checking the permissions and the specific path. If a user request is legit, we achieved our goal. If it’s an attacker that stole cookies, somehow they become “unauthenticated” in rest_cookie_check_errors. So the worst-case scenario here is a fallback to default permissions. To be on the safer side, though, it makes sense to modify the above code to also include the nonce check.

This method also has a drawback: no context is available about the request itself. It’s why the example above relies on $_SERVER to detect the need for intervention.

But wait, there’s more!

Are you still with me? Because there are, indeed, more places where we can intercept the result and block the request.

rest_pre_dispatch

Allow hijacking the request before dispatching by returning a non-empty. The returned value will be used to serve the request instead.

https://developer.wordpress.org/reference/hooks/rest_pre_dispatch/
// More context
add_filter( 'rest_pre_dispatch', function( $res, \WP_REST_Server $wp_rest_server, \WP_REST_Request $request ) {
	if ( this_needs_to_be_restricted() )
	return new \WP_Error(
		'rest_auth_required',
		'No REST for the restless!',
		[ 'status' => 401 ]
	);

	return $res;
}, 10, 3 );

What’s nice about this filter is that it runs very early during routing & dispatch, and you have access to the WP_REST_Server instance and to the request itself. This allows for finer granularity, as well as reducing wasted CPU cycles.

Logic-wise its description tells us that it’s for serving something as a substitute for the routed and processed request, something like serving a cached response for a very slow endpoint comes to mind.

So while it’s totally fine to return a WP_Error here, to me, it sounds a bit dirty.

rest_request_before_callbacks

Allows plugins to perform additional validation after a request is initialized and matched to a registered route, but before it is executed.

Note that this filter will not be called for requests that fail to authenticate or match to a registered route.

https://developer.wordpress.org/reference/hooks/rest_request_before_callbacks/
add_filter( 'rest_request_before_callbacks', function( $response, $handler, $request ) {
	if ( endpoint_needs_to_be_blocked() )
		return new \WP_Error(
			'rest_auth_required',
			'No REST for the restless!',
			[ 'status' => 401 ]
		);

	return $response;
}, 10, 3 );

This filter happens after all request parameters were validated and sanitized. If validation fails, this filter won’t be called.

rest_dispatch_request

Filters the REST dispatch request result.

https://developer.wordpress.org/reference/hooks/rest_dispatch_request/

This filter fires right before the request is dispatched (meaning it’s handler function/method is called).

This filter doesn’t fire if the route’s permission callback returned WP_Error.

add_filter( 'rest_dispatch_request', function( $res, \WP_REST_Request $request, string $route, $handler ) {
	if ( ! current_user_can( 'edit_others_posts' ) )
		return new \WP_Error(
			'rest_auth_required',
			'No REST for the restless!',
			[ 'status' => 401 ] 
		);

	return $res;
}, 10, 4 );

rest_request_after_callbacks

Filters the response immediately after executing any REST API callbacks.

https://developer.wordpress.org/reference/hooks/rest_request_after_callbacks/
add_filter( 'rest_request_after_callbacks', function( $response, $handler, $request ) { 
// you know the drill at this point 
return $response;
} );

Filtering at this point is wasteful, you have already generated the response, why block it now?

Conclusion

Hopefully, you’ve learned something new after reading this post (I know I did while writing it).

Treat yourself to this timeless classic.
Categories
Personal

Building Felice Donna Sleepwear: Part 1

One day my wife Maria’s friend Veronika was shopping for a silk robe or a silk pajama. Much to her chagrin, products she looked at were either costly or poorly made or combination of both. You’d think that the price would correlate with quality, but it’s definitely not the case for this category of products. She called Maria and told all about it. Maria, in turn, performed her own independent research, which ultimately confirmed Veronika’s findings.

So they had an idea: what if silk sleepwear products could be both affordable and made of quality fabric, what if these products were both comfortable and good looking? Thus, Felice Donna Sleepwear was born. Felice Donna [felitʃe dˈɔnna] means “Happy Woman” from Italian.

The work has begun in mid-2018. It was a lengthy process: from the inception to sourcing the Italian fabric and French lace to tinkering with numerous variants of patterns for prototypes to finally nailing it down and sewing the finished product.

None of it was easy, and I applaud Maria, who was juggling her primary job, pregnancy, and the new business. And I wanted to support her beyond encouraging words and an occasional idea or commentary.

Seeing how I don’t know much about the fashion industry in general, and even less so about silk sleepwear, I could only offer one thing. I promised to build the brand’s website when the time comes.

After all, I’ve been a web developer for more than half of my life, and it seemed only logical. Sure they could use one of the shopping platforms, but that would mean they’d lose a chunk of the profit and be subject to a vendor lockdown. Sure they could hire somebody to build a website, but that would mean extra expenses on a razor-thin budget with a hard-to-predict outcome. All my career, I’ve been developing someone else’s products, so it’s time to create a product for myself (well, not for me; for her, but she’s my better half, so that checks out). And with that thought, I’ve embarked on a fascinating journey.

Admittedly, there were challenges I haven’t anticipated. Some of them were technical. Others laid purely in social dynamics because, of course, having your immediate family as your client might get tricky for many reasons. I’m going to spare you from the “soft skills” part and instead focus on the technical aspects.

In the next part of this series, I’ll talk about some architectural and design decisions I had to make and the reasons behind them.

Categories
Personal

Hot Take: Problems and Solutions

Coming up with complex solutions for complex problems is easy.
Coming up with simple solutions for complex problems is hard.

What I mean by this is, generally speaking, a problem can be solved by breaking it down into smaller problems and addressing those. Once the individual pieces are taken care of, one can tie those together neatly, thus addressing the original issue.

But that’s in theory. In practice, each new small piece might create its own set of problems. It’ll likely introduce new inflection points at which things might go wrong. Little did you know, instead of one big problem, you now have a set of small ones, each of them potentially leading to new ones.

So yeah, coming up with simple solutions is hard, but, at the end of the day, you’ll do yourself a favor by not having to deal with the complexity you may have created otherwise.

Categories
Personal

Welcome to the N-th Iteration of My Blog

Most likely, it’ll end up abandoned just as previous iterations were. But I’ll give it a shot. I hope it’s going to consist of a healthy mix of personal rants and web development tips and tricks.