mirror of
https://github.com/strapi/strapi.git
synced 2025-08-21 07:09:31 +00:00
Merge branch 'master' into fix/profile-button-redirect-to-incorrect-url-format
This commit is contained in:
commit
8d69c8db38
@ -197,6 +197,7 @@ module.exports = {
|
|||||||
'/3.0.0-beta.x/guides/process-manager',
|
'/3.0.0-beta.x/guides/process-manager',
|
||||||
'/3.0.0-beta.x/guides/jwt-validation',
|
'/3.0.0-beta.x/guides/jwt-validation',
|
||||||
'/3.0.0-beta.x/guides/api-token',
|
'/3.0.0-beta.x/guides/api-token',
|
||||||
|
'/3.0.0-beta.x/guides/auth-request',
|
||||||
'/3.0.0-beta.x/guides/error-catching',
|
'/3.0.0-beta.x/guides/error-catching',
|
||||||
'/3.0.0-beta.x/guides/secure-your-app',
|
'/3.0.0-beta.x/guides/secure-your-app',
|
||||||
'/3.0.0-beta.x/guides/external-data',
|
'/3.0.0-beta.x/guides/external-data',
|
||||||
|
172
docs/3.0.0-beta.x/guides/auth-request.md
Normal file
172
docs/3.0.0-beta.x/guides/auth-request.md
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
# Authenticated request
|
||||||
|
|
||||||
|
In this guide you will see how you can request the API as an authenticated user.
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
To show you many of the concepts on the [roles and permissions](../plugins/users-permissions.md#manage-roles-permissions) part, we will use many users and roles.
|
||||||
|
|
||||||
|
After that we will see the [authentication workflow](../plugins/users-permissions.md#authentication) to get a `JWT` and use it for an API request.
|
||||||
|
|
||||||
|
We will have one group of users that will be able to only fetch **Articles** and an other group that will be able to fetch, create and update **Articles**.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
### Create Content Type
|
||||||
|
|
||||||
|
Lets create a new Content Type **Article**
|
||||||
|
|
||||||
|
- Click on `Content Type Builder` in the left menu
|
||||||
|
- Then `+ Create new content-type`
|
||||||
|
- Fill `Display name` with `article`
|
||||||
|
- Create 2 fields
|
||||||
|
- **Text** short named `title`
|
||||||
|
- **Rich text** named `content`
|
||||||
|
- And save this new Content Type
|
||||||
|
|
||||||
|
Then create some **Articles** from the Content Manager.
|
||||||
|
|
||||||
|
### Create Roles & Permissions
|
||||||
|
|
||||||
|
We will create 2 new groups to manage available actions for different kind of users.
|
||||||
|
|
||||||
|
- Click on `Roles & Permissions` in the left menu
|
||||||
|
- Then `+ Add New Role`
|
||||||
|
- Fill `name` with `Author`
|
||||||
|
- Check `Select All` for the Application Article Content Type.
|
||||||
|
- And save the new role
|
||||||
|
|
||||||
|
And repeat the opperation for the `Reader` group and check `find`, `findOne` and `count`.
|
||||||
|
|
||||||
|
### Create users
|
||||||
|
|
||||||
|
Finally create **2 users** with the following data.
|
||||||
|
|
||||||
|
**User 1**
|
||||||
|
|
||||||
|
- **username**: author
|
||||||
|
- **email**: author@strapi.io
|
||||||
|
- **password**: strapi
|
||||||
|
- **role**: Author
|
||||||
|
|
||||||
|
**User 2**
|
||||||
|
|
||||||
|
- **username**: reader
|
||||||
|
- **email**: reader@strapi.io
|
||||||
|
- **password**: strapi
|
||||||
|
- **role**: Reader
|
||||||
|
|
||||||
|
## Login as a Reader
|
||||||
|
|
||||||
|
To login as a user your will have to follow the [login documentation](../plugins/users-permissions.md#login).
|
||||||
|
|
||||||
|
Here is the API route for the authentication `/auth/local`.
|
||||||
|
|
||||||
|
You have to request it in **POST**.
|
||||||
|
|
||||||
|
:::: tabs
|
||||||
|
|
||||||
|
::: tab axios
|
||||||
|
|
||||||
|
```js
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const { data } = await axios.post('http://localhost:1337/auth/local', {
|
||||||
|
identifier: 'reader@strapi.io',
|
||||||
|
password: 'strapi',
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: tab Postman
|
||||||
|
|
||||||
|
If you are using **Postman** for example you will have to set the `body` as `raw` with the `JSON (application/json)` type.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"identifier": "reader@strapi.io",
|
||||||
|
"password": "strapi"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::::
|
||||||
|
|
||||||
|
The API response contains the **user's JWT** in the `jwt` key.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTc2OTM4MTUwLCJleHAiOjE1Nzk1MzAxNTB9.UgsjjXkAZ-anD257BF7y1hbjuY3ogNceKfTAQtzDEsU",
|
||||||
|
"user": {
|
||||||
|
"id": 1,
|
||||||
|
"username": "reader",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You will have to store this `JWT` in your application, it's important because you will have to use it the next requests.
|
||||||
|
|
||||||
|
### Fetch articles
|
||||||
|
|
||||||
|
Let's fetch Articles you created.
|
||||||
|
|
||||||
|
To do so, you will have to fetch `/articles` route in **GET**.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const { data } = await axios.get('http://localhost:1337/articles');
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
```
|
||||||
|
|
||||||
|
Here you should receive a **403 error** because you are not allowed, as Public user, to access to the **articles**.
|
||||||
|
|
||||||
|
You should use the `JWT` in the request to say that you can access to this data as **Reader user**.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const { data } = await axios.get('http://localhost:1337/articles', {
|
||||||
|
headers: {
|
||||||
|
Authorization:
|
||||||
|
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTc2OTM4MTUwLCJleHAiOjE1Nzk1MzAxNTB9.UgsjjXkAZ-anD257BF7y1hbjuY3ogNceKfTAQtzDEsU',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
```
|
||||||
|
|
||||||
|
And tada you have access to the data.
|
||||||
|
|
||||||
|
### Create an Article
|
||||||
|
|
||||||
|
To do so, you will have to request the `/articles` route in **POST**.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const {data} = await axios
|
||||||
|
.get('http://localhost:1337/articles', {
|
||||||
|
data: {
|
||||||
|
title: 'my article'
|
||||||
|
content: 'my super article content'
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTc2OTM4MTUwLCJleHAiOjE1Nzk1MzAxNTB9.UgsjjXkAZ-anD257BF7y1hbjuY3ogNceKfTAQtzDEsU'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
```
|
||||||
|
|
||||||
|
If you request this as a **Reader user**, you will receive a **403 error**. It's because the **Reader role** does not have access to the create function of the **Article** Content Type.
|
||||||
|
|
||||||
|
To fix that you will have to login with the **Author user** and use its `JWT` into the request to create an **Article**.
|
||||||
|
|
||||||
|
With that done, you will be able to create an **Article**.
|
@ -19,6 +19,10 @@ Starting from beta.18 the database packages have been changed to allow future ch
|
|||||||
|
|
||||||
Update your package.json accordingly:
|
Update your package.json accordingly:
|
||||||
|
|
||||||
|
:::: tabs
|
||||||
|
|
||||||
|
::: tab bookshelf
|
||||||
|
|
||||||
**Before**
|
**Before**
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@ -46,20 +50,68 @@ Update your package.json accordingly:
|
|||||||
{
|
{
|
||||||
//...
|
//...
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"strapi": "3.0.0-beta.18",
|
"strapi": "3.0.0-beta.18.3",
|
||||||
"strapi-admin": "3.0.0-beta.18",
|
"strapi-admin": "3.0.0-beta.18.3",
|
||||||
"strapi-connector-bookshelf": "3.0.0-beta.18",
|
"strapi-connector-bookshelf": "3.0.0-beta.18.3",
|
||||||
"strapi-plugin-content-manager": "3.0.0-beta.18",
|
"strapi-plugin-content-manager": "3.0.0-beta.18.3",
|
||||||
"strapi-plugin-content-type-builder": "3.0.0-beta.18",
|
"strapi-plugin-content-type-builder": "3.0.0-beta.18.3",
|
||||||
"strapi-plugin-email": "3.0.0-beta.18",
|
"strapi-plugin-email": "3.0.0-beta.18.3",
|
||||||
"strapi-plugin-graphql": "3.0.0-beta.18",
|
"strapi-plugin-graphql": "3.0.0-beta.18.3",
|
||||||
"strapi-plugin-upload": "3.0.0-beta.18",
|
"strapi-plugin-upload": "3.0.0-beta.18.3",
|
||||||
"strapi-plugin-users-permissions": "3.0.0-beta.18",
|
"strapi-plugin-users-permissions": "3.0.0-beta.18.3",
|
||||||
"strapi-utils": "3.0.0-beta.18"
|
"strapi-utils": "3.0.0-beta.18.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: tab mongoose
|
||||||
|
|
||||||
|
**Before**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
//...
|
||||||
|
"dependencies": {
|
||||||
|
"strapi": "3.0.0-beta.17.4",
|
||||||
|
"strapi-admin": "3.0.0-beta.17.4",
|
||||||
|
"strapi-hook-mongoose": "3.0.0-beta.17.4", // rename to strapi-connector-mongoose
|
||||||
|
"strapi-plugin-content-manager": "3.0.0-beta.17.4",
|
||||||
|
"strapi-plugin-content-type-builder": "3.0.0-beta.17.4",
|
||||||
|
"strapi-plugin-email": "3.0.0-beta.17.4",
|
||||||
|
"strapi-plugin-graphql": "3.0.0-beta.17.4",
|
||||||
|
"strapi-plugin-upload": "3.0.0-beta.17.4",
|
||||||
|
"strapi-plugin-users-permissions": "3.0.0-beta.17.4",
|
||||||
|
"strapi-utils": "3.0.0-beta.17.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**After**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
//...
|
||||||
|
"dependencies": {
|
||||||
|
"strapi": "3.0.0-beta.18.3",
|
||||||
|
"strapi-admin": "3.0.0-beta.18.3",
|
||||||
|
"strapi-connector-mongoose": "3.0.0-beta.18.3",
|
||||||
|
"strapi-plugin-content-manager": "3.0.0-beta.18.3",
|
||||||
|
"strapi-plugin-content-type-builder": "3.0.0-beta.18.3",
|
||||||
|
"strapi-plugin-email": "3.0.0-beta.18.3",
|
||||||
|
"strapi-plugin-graphql": "3.0.0-beta.18.3",
|
||||||
|
"strapi-plugin-upload": "3.0.0-beta.18.3",
|
||||||
|
"strapi-plugin-users-permissions": "3.0.0-beta.18.3",
|
||||||
|
"strapi-utils": "3.0.0-beta.18.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::::
|
||||||
|
|
||||||
Then run either `yarn install` or `npm install`.
|
Then run either `yarn install` or `npm install`.
|
||||||
|
|
||||||
## Database configuration
|
## Database configuration
|
||||||
@ -68,6 +120,10 @@ Now that you have installed the new database package. You need to update your `d
|
|||||||
|
|
||||||
You can now only use the connector name instead of the complete package name.
|
You can now only use the connector name instead of the complete package name.
|
||||||
|
|
||||||
|
:::: tabs
|
||||||
|
|
||||||
|
::: tab bookshelf
|
||||||
|
|
||||||
**Before**
|
**Before**
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@ -104,6 +160,91 @@ You can now only use the connector name instead of the complete package name.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: tab mongoose
|
||||||
|
|
||||||
|
**Before**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"defaultConnection": "default",
|
||||||
|
"connections": {
|
||||||
|
"default": {
|
||||||
|
"connector": "strapi-hook-mongoose",
|
||||||
|
"settings": {
|
||||||
|
//...
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**After**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"defaultConnection": "default",
|
||||||
|
"connections": {
|
||||||
|
"default": {
|
||||||
|
"connector": "mongoose",
|
||||||
|
"settings": {
|
||||||
|
//...
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::::
|
||||||
|
|
||||||
|
## Adding new root page files
|
||||||
|
|
||||||
|
We created new home pages when your go to your api url.
|
||||||
|
You will need to copy `index.html` and `production.html` into your `public` folder.
|
||||||
|
You can find those two files [here](https://github.com/strapi/strapi/tree/master/packages/strapi-generate-new/lib/resources/files/public).
|
||||||
|
|
||||||
|
## Updating `csp` options
|
||||||
|
|
||||||
|
The admin panel contains certain assets that use `data:img;base64` images. To allow rendering of those assets you can update the files `./config/environments/{env}/security.json` as follows:
|
||||||
|
|
||||||
|
**Before**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"csp": {
|
||||||
|
"enabled": true,
|
||||||
|
"policy": [
|
||||||
|
{
|
||||||
|
"img-src": "'self' http:"
|
||||||
|
},
|
||||||
|
"block-all-mixed-content"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
//....
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**After**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"csp": {
|
||||||
|
"enabled": true,
|
||||||
|
"policy": ["block-all-mixed-content"]
|
||||||
|
}
|
||||||
|
//....
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need more fine control you can also simply add the `data:` option to the `img-src` option.
|
||||||
|
|
||||||
## `ctx.state.user`
|
## `ctx.state.user`
|
||||||
|
|
||||||
Previously the ctx.state.user was populated with the user informations, its role and permissions. To avoid perfromance issues the role is the only populated relation on the user by default.
|
Previously the ctx.state.user was populated with the user informations, its role and permissions. To avoid perfromance issues the role is the only populated relation on the user by default.
|
||||||
@ -112,11 +253,11 @@ Previously the ctx.state.user was populated with the user informations, its role
|
|||||||
|
|
||||||
The file model has been updated. The `size` field is now a decimal number, allowing correct sorting behavior.
|
The file model has been updated. The `size` field is now a decimal number, allowing correct sorting behavior.
|
||||||
|
|
||||||
You will need to clear some database indexes if you are using either Mysql or PostgreSQL.
|
You will need to clear some database indexes if you are using either MySQL or PostgreSQL.
|
||||||
|
|
||||||
:::: tabs
|
:::: tabs
|
||||||
|
|
||||||
::: tab Mysql
|
::: tab MySQL
|
||||||
|
|
||||||
Run the following statement in your database:
|
Run the following statement in your database:
|
||||||
|
|
||||||
@ -298,7 +439,7 @@ RENAME COLUMN group_id to component_id;
|
|||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
::: tab Mysql
|
::: tab MySQL
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
-- renaming the table
|
-- renaming the table
|
||||||
@ -342,7 +483,7 @@ RENAME TO components_new_table_name;
|
|||||||
```
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
::: tab Mysql
|
::: tab MySQL
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
-- renaming the table
|
-- renaming the table
|
||||||
@ -463,47 +604,6 @@ db.getCollection('contentTypeCollection').update(
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Adding new root page files
|
|
||||||
|
|
||||||
We created new home pages when your go to your api url.
|
|
||||||
You will need to copy `index.html` and `production.html` into your `public` folder.
|
|
||||||
You can find those two files [here](https://github.com/strapi/strapi/tree/master/packages/strapi-generate-new/lib/resources/files/public).
|
|
||||||
|
|
||||||
## Updating `csp` options
|
|
||||||
|
|
||||||
The admin panel contains certain assets that use `data:img;base64` images. To allow rendering of those assets you can update the files `./config/environments/{env}/security.json` as follows:
|
|
||||||
|
|
||||||
**Before**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"csp": {
|
|
||||||
"enabled": true,
|
|
||||||
"policy": [
|
|
||||||
{
|
|
||||||
"img-src": "'self' http:"
|
|
||||||
},
|
|
||||||
"block-all-mixed-content"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
//....
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**After**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"csp": {
|
|
||||||
"enabled": true,
|
|
||||||
"policy": ["block-all-mixed-content"]
|
|
||||||
}
|
|
||||||
//....
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If you need more fine control you can also simply add the `data:` option to the `img-src` option.
|
|
||||||
|
|
||||||
## Rebuilding your administration panel
|
## Rebuilding your administration panel
|
||||||
|
|
||||||
Now delete the `.cache` and `build` folders. Then run `yarn develop`.
|
Now delete the `.cache` and `build` folders. Then run `yarn develop`.
|
||||||
|
@ -111,3 +111,42 @@ If you want to create your own provider without publishing it on **npm** you can
|
|||||||
```
|
```
|
||||||
|
|
||||||
- Finally, run `yarn install` or `npm install` to install your new custom provider.
|
- Finally, run `yarn install` or `npm install` to install your new custom provider.
|
||||||
|
|
||||||
|
## Trouble shooting
|
||||||
|
|
||||||
|
You received an `Auth.form.error.email.invalid` error even though the email is valid and exists in the database.
|
||||||
|
|
||||||
|
Here is the error response you get from the API.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"statusCode": 400,
|
||||||
|
"error": "Bad Request",
|
||||||
|
"message": [
|
||||||
|
{
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"id": "Auth.form.error.email.invalid"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This error is due to your IP connection. By default, Strapi uses the [`sendmail`](https://github.com/guileen/node-sendmail) package.
|
||||||
|
|
||||||
|
This package sends an email from the server it runs on. Depending on the network you are on, the connection to the SMTP server could fail.
|
||||||
|
|
||||||
|
Here is the `sendmail` error.
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: SMTP code:550 msg:550-5.7.1 [87.88.179.13] The IP you're using to send mail is not authorized to
|
||||||
|
550-5.7.1 send email directly to our servers. Please use the SMTP relay at your
|
||||||
|
550-5.7.1 service provider instead. Learn more at
|
||||||
|
550 5.7.1 https://support.google.com/mail/?p=NotAuthorizedError 30si2132728pjz.75 - gsmtp
|
||||||
|
```
|
||||||
|
|
||||||
|
To fix it, I suggest you to use another email provider that uses third party to send emails.
|
||||||
|
|
||||||
|
When using a third party provider, you avoid having to setup a mail server on your server and get extra features such as email analytics.
|
||||||
|
@ -343,6 +343,7 @@ const forms = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
[fields.divider],
|
[fields.divider],
|
||||||
|
[fields.private],
|
||||||
[fields.required],
|
[fields.required],
|
||||||
[fields.unique],
|
[fields.unique],
|
||||||
];
|
];
|
||||||
|
@ -82,6 +82,18 @@ const fields = {
|
|||||||
},
|
},
|
||||||
validations: {},
|
validations: {},
|
||||||
},
|
},
|
||||||
|
private: {
|
||||||
|
autoFocus: false,
|
||||||
|
name: 'private',
|
||||||
|
type: 'checkbox',
|
||||||
|
label: {
|
||||||
|
id: getTrad('form.attribute.item.privateField'),
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
id: getTrad('form.attribute.item.privateField.description'),
|
||||||
|
},
|
||||||
|
validations: {},
|
||||||
|
},
|
||||||
unique: {
|
unique: {
|
||||||
autoFocus: false,
|
autoFocus: false,
|
||||||
name: 'unique',
|
name: 'unique',
|
||||||
|
@ -77,6 +77,8 @@
|
|||||||
"form.attribute.item.requiredField": "Required field",
|
"form.attribute.item.requiredField": "Required field",
|
||||||
"form.attribute.item.requiredField.description": "You won't be able to create an entry if this field is empty",
|
"form.attribute.item.requiredField.description": "You won't be able to create an entry if this field is empty",
|
||||||
"form.attribute.item.settings.name": "Settings",
|
"form.attribute.item.settings.name": "Settings",
|
||||||
|
"form.attribute.item.privateField": "Private field",
|
||||||
|
"form.attribute.item.privateField.description": "This field will not show up in the API response",
|
||||||
"form.attribute.item.uniqueField": "Unique field",
|
"form.attribute.item.uniqueField": "Unique field",
|
||||||
"form.attribute.item.uniqueField.description": "You won't be able to create an entry if there is an existing entry with identical content",
|
"form.attribute.item.uniqueField.description": "You won't be able to create an entry if there is an existing entry with identical content",
|
||||||
"form.attribute.media.option.multiple": "Multiple media",
|
"form.attribute.media.option.multiple": "Multiple media",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user