Strapi is the next-gen headless CMS. It is open-source, Javascript, enabling content-rich experiences to be created, managed, and exposed to any digital device.
The name Strapi summarizes what the open-source project does well, allowing you to create your API from scratch using a point-and-click interface. Developers can easily personalize their API for custom implementation or custom logic.
We believe efficient communication when reviewing, and writing code is essential for productive tech teams. Axolo is a tool to enable developers to engage and communicate easily around pull requests. We integrate via GitHub and Slack. Axolo creates a temporary Slack channel for every pull request so that you can discuss the pull request with your colleagues quickly and with the proper context (code review comments, code comments, GitHub checks, and GitHub actions).
Strapi runs our backend and handles all the programming logic with our database. Strapi helped set up the models and create routes to interact with the GitHub and Slack API. It also gives an excellent base for scaling a project with the proper structure (controllers, services, API, policies, models, etc.).
According to the Strapi documentation, "Policies are functions that execute specific logic on each request before it reaches the controller. They are mostly used for securing business logic."
Policies are placed in your router and can be found under your models /routes
folder. Usually inside api/{modelname}/routes/{modelname}.js
.
Strapi policies allow you to create rules for your routes. Whenever you need to implement a rule for a route, you can add a policy to your router for the selected route. It helps keep your code DRY (don’t repeat yourself) and prevents your controller from being surcharged. I personally often find myself re-using routes I made a while ago.
To create a policy, you need to create a folder in your src
called policies.
You can give it the name that you feel is more appropriate. The name of the file will be the name of the policy in your routes.
To apply a policy to a route, you need to add a key to your route object as stated in the Strapi documentation:
1 // path: ./src/api/restaurant/routes/router.js
2 module.exports = {
3 routes: [
4 {
5 method: 'GET',
6 path: '/restaurants',
7 handler: 'Restaurant.find',
8 config: {
9 /**
10 Before executing the find action in the Restaurant.js controller,
11 we call the global 'is-authenticated' policy,
12 found at ./src/policies/is-authenticated.js.
13 */
14 policies: ['global::is-authenticated']
15 }
16 }
17 ]
18 }
The policies key takes an array as an argument. You can add multiple policies to a single route if you like. Also, the policy name is the name of the file.
How do we use Policies at Axolo: There are three (3) main ways we use policies at Axolo. Here is the list with code examples:
This policy helps us determine if somebody making a request is an admin within his organization.
Within Axolo we have two types of users:
Both types of users are signed in to our service but only the administrator can edit the settings. To add a layer of security to our frontend, we used a Strapi policy, see below:
1 // path: ./src/policies/is-organization-admin.js
2
3 module.exports = (policyContext, config, { strapi }) => {
4 if (policyContext.state.user.isAdmin) {
5 return true
6 }
7 return 401;
8 };
Some Axolo features are dedicated to paid customers. We’ve ensured a non-paying user cannot access those routes by adding an is-paying-organization
policy. Our user model has and belongs to an organization model.
1 // src/policies/is-paying-org.js
2 module.exports = (policyContext, config, { strapi }) => {
3 const id = policyContext.state.user.organization;
4 const organization = await strapi.query('organization').findOne({ id });
5 const { plan } = organization;
6 if (plan === 'professional' || plan === 'trial') {
7 return true;
8 }
9 return false
10 };
We use Heroku as a hosting platform and Heroku scheduler as a cron job. These cron jobs work by calling a specific route in our backend. Heroku only allows three possibilities for the cron job to be contacted: every 10 minutes, every hour, or every day. Since some of our actions only need to be run during the week, on a specific day, or only during weekends, we have a dedicated policy for each of those cases.
Here is an example of a policy that checks if it's a weekday (Monday, Tuesday, Wednesday, Thursday, or Friday).
1 // src/policies/is-weekday-today.js
2 const moment = require('moment');
3
4 module.exports = (policyContext, config, { strapi }) => {
5 const date = moment();
6 const day = date.day();
7 if (day >= 1 && day <= 5) {
8 return true
9 }
10 return false
11 };
Policies are helpful to keep your controllers DRY (don't repeat yourself). If you see yourself using the same code over two controllers or think you could be reusing some of the logic you implement in a controller, it probably is a good idea to create a policy for that.
Do you have any other use case for policies? Share them below so that anyone reading this article can get inspired by your way of having policies.