![](https://appicsoftwares.com/blog/wp-content/uploads/2023/11/Comfortaa-Bold-2023-11-30T181605.511-min.png)
A headless content management system called Strapi is used to create backend apps. Strapi lets you personalize your backend with policies, middleware, controllers, services, models, and webhooks if you know how to code in JavaScript.
You will discover more about policies and their application in this post. Now let’s get going!
Overview of policies
Consider going into a bank and wanting to deposit money there. Banks, as you may know, have restrictions that limit what you are allowed to carry into the institution. To make sure that no one breaks any policies, the bank may install security checks at its entry.
Security will advise you to leave the facility and address the problem if it isn’t already worse if you break a policy. The security lets you into the building as long as you don’t break any rules.
Requests in computing use routes to deliver data to the server. Requests enter through the routes. You can set up policies with Strapi to verify these requests at a route before they reach the server. For a request to be approved, it must not contravene any policies.
Strictly speaking, a policy is a function that establishes a rule for each request that comes into the server. The request is accepted by the server if the function returns true. The request is denied if the function returns false. Policies that contain your unique regulations can be created.
You can make the following kinds of policies in Strapi:
- worldwide regulations without a focus.
- scoped API policies for an API.
- policies scoped to specific plugins.
worldwide policies
A global policy can be initialized in one of the following ways:
- Applying the command strapi create.
- generating the JavaScript file by hand.
- launching a worldwide policy
Run the yarn strapi create command and do the following actions to initialize a global policy:
- Decide on a policy.
- Enter the name of your insurance.
- Choose “Add policy to project root.”
$strapi$ produces
? Strapi Generators policy: Produce an API policy
Policy name: primary policy
? Where would you like to see this policy added? Put a policy at the project’s foundation.
++ /policies/first-policy.js
✨ Completed in 28.56 seconds.
First-policy, a global policy I recently developed, is located in the src/policies folder.
This is an illustration of a file that is generated automatically:
module.exports = (config, { strapi }, policyContext) => {
// Here, add your own reasoning.
(“In first-policy policy.”); strapi.log.info;
const canDoSomething is set to true.
suppose (canDoSomething) {
return the truth;
~
return a false positive;
};
I’m going to add one more console as well.log into our policy to make it more visible.
(“In first-policy policy.”); strapi.log.info;
The global policy number is #################; console.log(“#################”);
Now that we have a basic content type developed, let’s set it up for our real-world example so we can test the newly formed global policy.
You can use the npx create-strapi-app@latest my-project –quickstart to create your Strapi app right now if you haven’t already. Once your project has been created, proceed as indicated below.
Step 1: Configure the content type of the item
- Setting up the content type to store data is the first thing you should do. This project’s content type will include fields for name, code, and price.
- To generate the content type, take the following actions:
- To open the API creation interface, click Content-Type Builder.
- To establish a new API, select + establish a new collection type.
- Select “Item” as the display name and click on the Next button.
Make the following changes to the “name” field:
- text as the data type
- field name with “name” in it
- text size as short text
- To add a field, click + Add another field.
Make the following changes to the “code” field:
- text as the data type
- “code” as the field name
- text size in short text format.
- To add a field, click + Add another field.
Make the following changes to the “price” field:
- Number as the data type
- “price” as the field name
- decimal representation of the number
- To complete adding fields to the content-type, click Finish.
- To register your content-type, click Save.
- Go ahead and publish after adding at least one item.
Step 2: Configure the pathways
To proceed with the project, you must configure an API that enables data manipulation and access from outside apps into Item. There will be routes in the API for obtaining, adding, changing, and removing data.
The steps listed below can be used to build up the routes for Item:
- Go to Settings.
- Under Users & Permissions, select Roles.
- To view the setup for public users, click public.
- Invert the item dropdown menu.
To enable public users to get, edit, add, and remove data from this item, click Select All.
To make the changes go into effect, click save.
Now that we have our endpoint tested, we can use Postman or Insomnia.
Alternatively, we can test it locally in the browser by going to http://localhost:1337/api/items if we are doing a GET request.
This is the answer we receive.
~
“information”: [
~
“id”: a single
“characteristics”: {
“name” : “Desk” ,
“code” : “98932” ,
“cost”: $10.99,
“createdAt” : “2023-09-06T17:01:53.934Z” ,
“updatedAt” : “2023-09-06T17:01:54.508Z” ,
“publishedAt” : “2023-09-06T17:01:54.507Z”
~
~
],
“meta”: {
“pagination”: {
“page”: one
“pageSize”: 25
“pageCount”: one
“total”: one
~
~
~
Linking a worldwide policy to a path
Let’s now register the newly established policy to a route. This can be done in the API configuration file for the route.
To configure a global policy, follow these steps:
- Launch item.js from./src/api/item/routes.
- In createCoreRouter, add the policy to a route.
- require(“@strapi/strapi”).factories; const {createCoreRouter }
- createCoreRouter(“api::item.item”, module.exports) {
configuration: {
locate: {
regulations: [
/ refer to a legally registered policy
“global::first-policy” ,
// direct the user to a registered policy with unique settings
// { config: {} }, name: “global::policy-name”,
// directly pass the policy function
// (config, { strapi }, policyContext) => {
// give a true response;
// },
],
~,
~,
});
We should try again with a GET request to http://localhost:1337/api/items to see if our policy is generating the console log message.
Our policy’s log ought to be visible in the console right now.
Information from [2023-09-06 12:15:03.337]: In the initial policy.
International Policy #################
[2023-09-06 12:15:03.341] GET /api/items (13 ms) 200
Were you aware?
To launch our Strapi application in an interactive shell environment, use the yarn strapi console.
The strapi.policies program can then be used to view all of the available policies.
The output that follows should be visible.
~
“admin::isAuthenticatedAdmin”: [Anonymous Function],
“admin::possessesPermissions”: {
the name ‘admin::hasPermissions’,
validator: [WrappedValidator function],
handler: [The handler’s function]
~,
If “admin::isTelemetryEnabled,” then {
calling it ‘admin::isTelemetryEnabled’,
validator: [WrappedValidator function],
handler: [The handler’s function]
~,
‘global::first-policy’: [Anonymous Function],
‘plugin::content-manager.possesses-draft-and-publish’: [Anonymous Function],
‘content-manager.hasPermissions.plugin’: {
The plugin ‘plugin::content-manager.hasPermissions’
validator: [WrappedValidator function],
handler: [The handler’s function]
~
~
You can view the global policy we developed.
manually establishing a worldwide policy
The yarn strapi generate command just creates a boilerplate-filled./src/policies/[policy-name].js file.
You can manually repeat the action.
Make a file called./src/policies/[policy-name].js to establish a policy. Optionally, you can paste a boilerplate to begin going more quickly. As an illustration:
“use strict” ;
module.exports = (config, { strapi }, policyContext) => {
// Here, add your own reasoning.
“In the policy.” – strapi.log.info;
const canDoSomething is set to true.
suppose (canDoSomething) {
return the truth;
~
return a false positive;
};
Global::policy-name is the reference for global policies. Different references apply to different kinds of policies.
Now let’s examine the creation of API policies.
“use strict” ;
module.exports = (config, { strapi }, policyContext) => {
// Here, add your own reasoning.
“In the policy.” – strapi.log.info;
const canDoSomething is set to true.
suppose (canDoSomething) {
return the truth;
~
return a false positive;
};
Global::policy-name is the reference for global policies. Different references apply to different kinds of policies.
Now let’s examine the creation of API policies.
API regulations
Similar to global policies, there are comparable methods to initialize an API policy:
- Applying the command strapi create.
- generating the JavaScript file by hand.
- Initializing a yarn strapi create API policy
- Use the yarn strapi create command and the following instructions to initialize an API policy:
- Decide on a policy.
- Put your policy’s name here: second-policy.
- Click on Add policy to an already-existing API.
- Choose the API in which you wish to create your policy: item
$strapi$ produces
? Create an API policy using Strapi Generators.
? Second-policy term for the policy
? Where would you like to see this policy added? Adding a policy to an already-existing API
? For what API is this intended? item
++/api/item/policies/second-policy.js ✔
✨ Completed in 22.58 seconds.
In the file src/api/item/policies/second-policy.js, you may locate your just generated policy.
This is the file’s appearance.
module.exports = (config, { strapi }, policyContext) => {
// Here, add your reasoning.
(“In second-policy policy.”); strapi.log.info;
const canDoSomething is set to true.
suppose (canDoSomething) {
return the truth;
~
return a false positive;
};
To make it easier to find, I’m also going to include another console.log in our policy.
(“In second-policy policy.”); strapi.log.info;
Adding an API policy to a route registration
Setting up an API policy involves the same steps as setting up a global policy:
- Launch item.js from./src/api/item/routes.
- Here, we have already included our worldwide policy. Now let’s apply our API policy.
- if you are unable to recall the precise name of your coverage. Our earlier tip can help you locate it.
- Enter the following strapi.policies and press enter to launch the yarn strapi console in Strapi.
This is the list that you ought to see:
~
“admin::isAuthenticatedAdmin”: [Anonymous Function],
“admin::possessesPermissions”: {
the name ‘admin::hasPermissions’,
validator: [WrappedValidator function],
handler: [The handler’s function]
~,
If “admin::isTelemetryEnabled,” then {
calling it ‘admin::isTelemetryEnabled’,
validator: [WrappedValidator function],
handler: [The handler’s function]
~,
‘global::first-policy’: [Anonymous Function],
‘api::item.second-policy’: [Anonymous Function]
‘plugin::content-manager.possesses-draft-and-publish’: [Anonymous Function],
‘content-manager.hasPermissions.plugin’: {
The plugin ‘plugin::content-manager.hasPermissions’
validator: [WrappedValidator function],
handler: [The handler’s function]
~
~
Nicely, api::item.second-policy, our second policy, is now visible to you.
The file./src/api/item/routes/item.js has been changed.
require(“@strapi/strapi”).factories; const {createCoreRouter }
createCoreRouter(“api::item.item”, module.exports) {
configuration: {
locate: {
regulations: [
/ refer to a legally registered policy
“global::first-policy” ,
“api::item.second-policy” ,
// direct the user to a registered policy with unique settings
// { config: {} }, name: “global::policy-name”,
// directly pass the policy function
// (config, { strapi }, policyContext) => {
// give a true response;
// },
],
~,
~,
});
To check if we are receiving the console log message from our second policy, let’s do another GET request to http://localhost:1337/api/items.
Our log from both of our policies should now be visible.
Information from [2023-09-06 12:55:43.107] is in the first policy.
International Policy #################
[2023-09-06 12:55:43.108] details: Within the second policy.
200 [2023-09-06 12:55:43.111] http: GET /API/items (19 ms)
When a route is covered by an API policy, it is referenced using the policy-name. Use api::api-name.policy-name to refer to policies that are registered in a different API.
Manually creating an API policy
Make a file called.src/api/[api-name]/policies/[policy-name].js if you want to manually define a policy. To begin, you can optionally paste the following boilerplate into the file:
“use strict” ;
module.exports = (config, { strapi }, policyContext) => {
// Here, add your reasoning.
“In the policy.” – strapi.log.info;
const canDoSomething is set to true.
suppose (canDoSomething) {
return the truth;
~
return a false positive;
};
Policies for plugins
Moreover, policies may be scoped to plugins. Plugin policies are the name given to these kinds of policies. The plugin isAuthenticated from Users & Permissions is an illustration of a plugin policy. Any user submitting a request via a route that employs the authenticated policy must be authenticated for the request to be fulfilled.
A plugin policy can be initialized in one of two ways:
- Applying the command strapi create.
- generating the JavaScript file by hand.
- Utilizing strapi create to initialize a plugin policy
To initialize a plugin policy, run strapi create and take the following actions:
- Decide on a policy.
- Put the policy’s name in writing.
- Choose Upgrade an existing plugin with a policy.
- Choose the plugin in which you wish to register itz
Making by hand
Make a file called./src/plugins/[plugin-name]/policies/to manually establish a policy. You can start by optionally pasting this boilerplate:
“use strict” ;
module.exports = (config, { strapi }, policyContext) => {
// Here, add your reasoning.
“In the policy.” – strapi.log.info;
const canDoSomething is set to true.
suppose (canDoSomething) {
return the truth;
~
return a false positive;
};
Setting up in routes
Setting up a plugin policy is comparable to setting up global and API policies:
./src/api/[api-name]/routes/router.js should be opened.
In createCoreRouter, construct an object.
Include the policy in the array of policies.
require(“@strapi/strapi”).factories; const {createCoreRouter }
createCoreRouter(“api::restaurant.restaurant”, module.exports) {
configuration: {
locate: {
regulations: [
/ refer to a legally registered policy
“plugin::plugin-name.policy-name” ,
// direct the user to a registered policy with unique settings
{ config: {} }, name: “plugin::plugin-name.policy-name”,
// directly pass the policy function
(config, { strapi}, policyContext) => {
return the truth;
~,
],
~,
~,
});
Use plugin::plugin-name.policy-name to refer to a plugin policy.
Although this is outside the purview of this guide, you may also add plugin policies to API routes inside your plugin. Considering that an API endpoint-created plugin would be required.
Returning messages on policy failure
In certain situations, receiving a request error alone is insufficient when a policy fails. Some of you may be curious as to why the policy didn’t work.
A route with multiple policies linked to it serves as an example. Because every policy failure responds by default in the same way, it will be challenging to track down the failure.
Policies that fail under multiple conditions provide another illustration. It is difficult to determine which circumstance caused the policy to fail in the absence of a thorough error notice.
A policy can be set up to return messages if it fails. This is how you may complete the straightforward process:
Add the PolicyError class to the policy file by importing it:
require(“@strapi/utils”) const utils;
const = utils.errors; PolicyError
Toss a PolicyError object containing the error’s information and message:
If (error) {
throw new PolicyError(details, message, and error);
Otherwise, {
return the truth;
~
A real-world example using policies
Assume you are developing a store’s backend application. Right now, you’re developing an API that allows you to add, retrieve, and edit backend items. The backend needs the item’s name, code, and price to create it.
You can develop the project and policy by following these steps. Create a new Strapi project, then adhere to the instructions that follow.
With our item collecting type, we will utilize the Strapi app that we now have.
Construct the policy.
This project’s policy will ensure that any data supplied to the item’s created route adheres to a set format. A schema will be used to explain the format.
In case you are unaware, a schema is a description of the ideal structure for data.
We will use the Joi JavaScript library to build the schema. You can read this API reference if you’re not familiar with how Joi operates. Open the root folder of the project in your terminal, then type either of the following commands to install Joi:
# yarn
$ yarn + joi
# npm
$ npm install joi
You can now go to work on the policy.
First, go to src/api/item/policies and create a new API policy. The file can be called valid-input.js.
Now, insert the following code into the valid-input.js file located at./src/api/item/policies:
“use strict” ;
require(“joi”); const Joi =
require(“@strapi/utils”) const utils;
const = utils.errors; PolicyError
/**
* Policy for `valid input}
*/
module.exports = (config, { strapi }, policyContext) => {
// Obtain request body information
var requestData = body[“data”] in policyContext.request;
// Construct a schema for requesting body data validation.
Joi.object({) const schema =
Joi.string().required() is the name.
Joi.string() is the code.
[a-zA-Z0-9]{4}-.pattern(/^){3}[a-zA-Z0-9]{4}$/) // The format of the test is as follows: (four groups of alphanumeric characters, divided by hyphens)
.required(),
cost is Joi.number().necessary(),
});
// Verify the data in the request body.
const { error} = requestData.validate();
If (error) {
throw new PolicyError(error.details, “Invalid input data”);
Otherwise, {
// If the request body data is valid, allow the request to proceed.
return the truth;
~
};
This policy operates as follows:
- The software gathers the requested data on line 11.
- A schema with the required object format is created between lines 14 and 22.
- Line 25 contains a destructured error object after the schema evaluated the request data.
- If there is a mistake, the request is stopped between lines 27 and 32.
- In the event of an error, lines 32 through 36 permit the request to be processed.
- Let’s File Our Policy.
To register the policy, take the following actions:
- Add our recently established policy to the./src/api/item/routes/item.js file by opening it.
- Let’s add the following inside the config object.
produce: {
[“api::item.valid-input”] policies
~
The following is how the item.js file ought to appear:
- require(“@strapi/strapi”).factories; const {createCoreRouter }
- createCoreRouter(“api::item.item”, module.exports) {
configuration: {
produce: {
[“api::item.valid-input”] policies
~,
locate: {
regulations: [
/ refer to a legally registered policy
“global::first-policy” ,
“api::item.second-policy” ,
// direct the user to a registered policy with unique settings
// { name: “global::policy-name”, config: {} }
// directly pass the policy function
// (config, { strapi }, policyContext) => {
// give a true response;
// },
],
~,
~,
});
Let us try this new rule.
- We must test our endpoint using Postman or Insomnia since we will be sending a POST request.
- I’m going to use Insomnia.
- I will submit the following request inside of Insomnia.
- the-post-request.png
- Take note of how I’ve left every field empty.
- Our policy will cause the following error when we execute the following request.
~
“data”: void,
“Error”: {
“status”: 403,
“name” : “PolicyError” ,
“message” : “Invalid input data” ,
“specifics”: [
~
“message”: “\”name\” is not allowed to be empty”,
“path”: [“name”],
“type” : “string.empty” ,
“Context”: {
“label” : “name” ,
“value”: “,”
“key” : “name”
~
~
[
~
~
Now let’s submit a request with all fields completed.
We’ll send the information below:
~
“data”: {
“name” : “test” ,
“code” : “12e3-4r3d-35te-345a” ,
“price” : “9.99”
~
~
We now return a 200 status code and our item is generated after we pass valid data.
Good. Our strategy is effective. Fantastic work.
Conclusion
A strong foundation for customizing application logic, authorization, and authentication is offered by Strapi’s policies and customizations. With a highly configurable and secure backend, you can ensure efficiency and flexibility in your development projects.
If you’re looking for a Strapi development business to help you create an application using Strapi, another company you should look into is Appic Softwares. Through a range of projects, our talented team of Strapi developers has helped clients all over the world create Strapi apps.
Why then are you hesitant?