Merge branch 'master' into fix/profile-button-redirect-to-incorrect-url-format

This commit is contained in:
Abraham Cuenca 2019-12-26 13:54:34 -08:00 committed by GitHub
commit 8d69c8db38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 382 additions and 55 deletions

View File

@ -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',

View 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**.

View File

@ -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`.

View File

@ -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.

View File

@ -343,6 +343,7 @@ const forms = {
}, },
], ],
[fields.divider], [fields.divider],
[fields.private],
[fields.required], [fields.required],
[fields.unique], [fields.unique],
]; ];

View File

@ -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',

View File

@ -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",