# A practical dive into functional programming

## Implementing a permission system

Hi folks!

I've been working on a personal project, a simple Express.js REST API. But after a while, I got stuck on a simple problem: What is the best way to manage user permissions to certain routes in certain circumstances?

You may think that I could just add a bunch of `if` `else` in many different places to achieve that, but it would be a pain to debug, test, and mainly, change (trust me!).

So, I've come up with a solution that makes use of the functional paradigm, which is very powerful. In general, it was a nice solution that can be useful in real situations and I wanted to share this with you guys in hopes that you'll make more use of this wonderful paradigm. Enjoy it!

## Funcional programming

First of all, let's see what is functional programming and some core concepts that will be used in this example.

Functional programming is a way of writing code that uses pure functions, instead of classes, avoiding state changes and side effects.

It uses mathematical thinking of functions: they take an input and return an output. This approach has several benefits, like making it easier to write tests, as functions' behavior depends only on their parameters, and it forces modularity.

But, in functional programming, these function inputs and outputs can be other functions, not just values, and that's exactly where this strategy becomes powerful.

### Composition

Composition is the process of adding the result of a certain function as the input of another. This way, we can build little pieces of software that are reusable and that have only one responsibility (as it should always be).

``````const upperCase = (text) => text.toUpperCase();
const reverse = (text) => text.split("").reverse().join("");

// Composed function
const reverseAndUpperCase = (text) => upperCase(reverse(text));

reverseAndUpperCase("hello"); // OLLEH``````

### Higher order functions

These are special kinds of functions that work with other functions: they can take them as arguments or return a new function.

``````const applyLogger =
(func) =>
(...values) => {
console.log("called");
return func(...values);
};

const sayHello = applyLogger((name) => console.log(`Hello \${name}`));

sayHello("John");
// called
// Hello John``````

After seeing these, you might think "Ok, but how will it help me in my daily life?" and I think that is the part that most teachers get stuck on: they just don't apply the concepts and make it all sound useless. So, let's get our hands on some code!

## CODE!

### Setup

Let's do a quick ExpressJs project setup:

``yarn init -y && yarn install express moment``
``````// src/server.js

const express = require("express");

const app = express();

app.get("/actions/user", (req, res) => res.json({ message: "User action" }));

app.listen(3000);``````

Now, if we run `node src/server.js`, our server will run at localhost:3000.

### The problem

Note that in this application there're only 2 endpoints (`/action/admin` and `/action/user`). In the real world though, there could be a lot more, and some of them may have some really specific, but similar, permission rules, especially when you're dealing with monoliths.

Just imagine that you're working in a feature, like a new route, which has some pretty similar permission rules to another existing route, but applied in a different order, or that needs to do one extra step of validation and, at the end of the day, you need to write an entire functionality that does the almost same thing that has been written before. Yeah, that's not the best way to go.

The general approach of putting all validation in a huge function hurts the open-close principle and the single responsibility principle. Also changing working code, possibly not written by you, can lead to bugs and unexpected behavior.

### Permission rules

• `/actions/user`: someone can access this if they're a User, an Admin, or, send the correct time in the `HH:mm` format.
• `/actions/admin`: someone can access this if they're an Admin or a User and has sent the right time in the `HH:mm` format.

As this is a simple example, I won't be implementing a User system. This identification will be done just by sending an `x-identifier-token` with a UUID token. The time will be received in the `x-time` header.

### Making the permission system

For that, we need to make a permission maker: this is a high order function that creates a middleware that runs other permissions and lets it pass if any of them returns true, otherwise it returns a 401 status.

OBS: It is important to keep this `and|or` logic in mind to make it right.

Maybe some of you have already noticed, but this behavior sounds pretty much like a composition problem, and that's exactly what it is. So, let's make a composer that applies the `or` logic:

``````// src/lib/index.js

const orCompose =
(...funcs) =>
(value) =>
funcs.reduce((acc, func) => acc || func(value), false);

module.exports = { orCompose };``````

This `orCompose` function takes other functions, that should return a boolean value, as inputs and returns a new function that runs each function sequentially taking their results, passing them to the next iteration, and making comparisons. Therefore, we can combine behavior in a `or` logic.

Note that if one of the functions returns `true`, the following ones won't run.

``````// Example

const is1 = (value) => value === 1;
const is2 = (value) => value === 2;

const composed = orCompose(is1, is2);

composed(1); // true, is1 return true
composed(2); // true, is2 return true
composed(3); // false, both return false``````

Back to the main problem... In a real hole system, probably async operations (such as Database queries) would be done, so I'll change this a little so it can handle promises too.

``````// src/lib/index.js

const orCompose =
(...funcs) =>
(value) =>
funcs.reduce(
(acc, func) =>
Promise.resolve(acc).then((result) => result || func(value)),
false
);

module.exports = { orCompose };``````

Now, let's create the individual rules. We need to check, through the request object, to determine if the client is a User, an admin, has sent the right time, or is a user and has sent the right time:

``````// src/permission.js

const moment = require("moment");

// These should be env variables
const secretKeys = {
USER: "cf798a4f-2d8c-48ed-b56f-ae19c786c3be",
};

const isUser = async (req) =>

const isAdmin = async (req) =>

const isRightTime = async (req) =>

const isUserAndIsRightTime = async (req) =>

Note that each function has its pretty well-defined responsibility, which allows us the reuse them wherever we want, as well as test them individually.

To finish this, let's create a `makePermission` function:

``````// src/permission.js

const { orCompose } = require("./lib");

// ...

const makePermission =
(...permissions) =>
async (req, res, next) => {
const checker = orCompose(...permissions);
const result = await checker(req, res, next);

if (result) return next();
return res.status(401).send();
};

// ...``````

So, now we can just use `makePermission` to build a middleware that applies the given rules and use them in our `server.js` file.

``````// src/permission.js

// ...
module.exports = {
};``````
``````// src/server.js
const express = require("express");
const { userPermission, adminPermission } = require("./permission");

const app = express();

app.get("/actions/user", userPermission, (_req, res) =>
res.json({ message: "User action" })
);
);

app.listen(3000, () => console.log("Server running at 3000!"));``````

And now we have a working permission system with logic that isn't based on a bunch of `if/else` statements!

### BONUS

As I said, this `and|or` logic is important in this case. Our system is great for `or` logics, but not so much when it comes to `and` logics. This can be seen in the `isUserAndRightTime` function:

``````// src/permission.js

const isUserAndIsRightTime = async (req) =>

To avoid this ugly piece of code, we can create a Composer with an `and` logic, just like we've done before:

``````// src/lib/index.js

const andCompose =
(...funcs) =>
(value) =>
funcs.reduce(
(acc, func) =>
Promise.resolve(acc).then((result) => result && func(value)),
true
);

const orCompose =
(...funcs) =>
(value) =>
funcs.reduce(
(acc, func) =>
Promise.resolve(acc).then((result) => result || func(value)),
false
);

module.exports = { andCompose, orCompose };``````

Using these, we can use any combination of permissions to build complex statements (just like the logic operators `&&` and `||`).

Now, let's refactor our previous code.

``````// src/permission.js

const moment = require("moment");
const { andCompose, orCompose } = require("./lib");

const secretKeys = {
USER: "cf798a4f-2d8c-48ed-b56f-ae19c786c3be",
};

const makePermission =
(...permissions) =>
async (req, res, next) => {
const checker = orCompose(...permissions);
const result = await checker(req, res, next);

if (result) return next();
return res.status(401).send();
};

const isUser = async (req) =>

const isAdmin = async (req) =>

const isRightTime = async (req) =>

module.exports = {
};``````

And that's pretty much it!

## Final Thoughts

On this link, you can access the code produced during this post to see the full version.

I hope you've enjoyed this dive and that you now can see the power of using functional programming concepts in real-world problems.