diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 3b3bccb928..07e7ebd63e 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -197,6 +197,7 @@ module.exports = { '/3.0.0-beta.x/guides/process-manager', '/3.0.0-beta.x/guides/jwt-validation', '/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/secure-your-app', '/3.0.0-beta.x/guides/external-data', diff --git a/docs/3.0.0-beta.x/guides/auth-request.md b/docs/3.0.0-beta.x/guides/auth-request.md new file mode 100644 index 0000000000..dad2f7da93 --- /dev/null +++ b/docs/3.0.0-beta.x/guides/auth-request.md @@ -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**. diff --git a/docs/3.0.0-beta.x/migration-guide/migration-guide-beta.17-to-beta.18.md b/docs/3.0.0-beta.x/migration-guide/migration-guide-beta.17-to-beta.18.md index e9190b14cd..efdfd29fc2 100644 --- a/docs/3.0.0-beta.x/migration-guide/migration-guide-beta.17-to-beta.18.md +++ b/docs/3.0.0-beta.x/migration-guide/migration-guide-beta.17-to-beta.18.md @@ -19,6 +19,10 @@ Starting from beta.18 the database packages have been changed to allow future ch Update your package.json accordingly: +:::: tabs + +::: tab bookshelf + **Before** ```json @@ -46,20 +50,68 @@ Update your package.json accordingly: { //... "dependencies": { - "strapi": "3.0.0-beta.18", - "strapi-admin": "3.0.0-beta.18", - "strapi-connector-bookshelf": "3.0.0-beta.18", - "strapi-plugin-content-manager": "3.0.0-beta.18", - "strapi-plugin-content-type-builder": "3.0.0-beta.18", - "strapi-plugin-email": "3.0.0-beta.18", - "strapi-plugin-graphql": "3.0.0-beta.18", - "strapi-plugin-upload": "3.0.0-beta.18", - "strapi-plugin-users-permissions": "3.0.0-beta.18", - "strapi-utils": "3.0.0-beta.18" + "strapi": "3.0.0-beta.18.3", + "strapi-admin": "3.0.0-beta.18.3", + "strapi-connector-bookshelf": "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" } } ``` +::: + +::: 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`. ## 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. +:::: tabs + +::: tab bookshelf + **Before** ```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` 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. -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 -::: tab Mysql +::: tab MySQL Run the following statement in your database: @@ -298,7 +439,7 @@ RENAME COLUMN group_id to component_id; ::: -::: tab Mysql +::: tab MySQL ```sql -- renaming the table @@ -342,7 +483,7 @@ RENAME TO components_new_table_name; ``` ::: -::: tab Mysql +::: tab MySQL ```sql -- 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 Now delete the `.cache` and `build` folders. Then run `yarn develop`. diff --git a/docs/3.0.0-beta.x/plugins/email.md b/docs/3.0.0-beta.x/plugins/email.md index 3900c5a480..859a94d309 100644 --- a/docs/3.0.0-beta.x/plugins/email.md +++ b/docs/3.0.0-beta.x/plugins/email.md @@ -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. + +## 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. diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js index 1d3e4a0f61..e4192ad038 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js @@ -343,6 +343,7 @@ const forms = { }, ], [fields.divider], + [fields.private], [fields.required], [fields.unique], ]; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/staticFields.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/staticFields.js index 0c484f8b85..d9cf928c2a 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/staticFields.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/staticFields.js @@ -82,6 +82,18 @@ const fields = { }, 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: { autoFocus: false, name: 'unique', diff --git a/packages/strapi-plugin-content-type-builder/admin/src/translations/en.json b/packages/strapi-plugin-content-type-builder/admin/src/translations/en.json index be3c9e5fca..3a9778f290 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/translations/en.json +++ b/packages/strapi-plugin-content-type-builder/admin/src/translations/en.json @@ -77,6 +77,8 @@ "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.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.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",