diff --git a/README.md b/README.md index f91a0e382c..41c8629b0a 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ Complete installation requirements can be found in the documentation under Please refer to the [local plugins](../plugin-development/quick-start.md) section to know more. ---- - ## strapi install Install a plugin in the project. @@ -264,8 +260,6 @@ strapi install Some plugins have admin panel integrations, your admin panel might have to be rebuilt. This can take some time. ::: ---- - ## strapi uninstall Uninstall a plugin from the project. @@ -290,7 +284,13 @@ options [--delete-files] Some plugins have admin panel integrations, your admin panel might have to be rebuilt. This can take some time. ::: ---- +## strapi console + +Start the server and let you eval commands into your application in real time. + +```bash +strapi console +``` ## strapi version @@ -300,8 +300,6 @@ Print the current globally installed Strapi version. strapi version ``` ---- - ## strapi help List CLI commands. diff --git a/docs/3.0.0-beta.x/guides/deployment.md b/docs/3.0.0-beta.x/guides/deployment.md index 62a11f52df..0fd8a43834 100644 --- a/docs/3.0.0-beta.x/guides/deployment.md +++ b/docs/3.0.0-beta.x/guides/deployment.md @@ -493,7 +493,7 @@ sudo nano ecosystem.config.js module.exports = { apps : [{ name: 'your-app-name', - cwd: '/home/ubuntu/my-strapi-project/my-project' + cwd: '/home/ubuntu/my-strapi-project/my-project', script: 'npm', args: 'start', env: { diff --git a/docs/3.0.0-beta.x/guides/draft.md b/docs/3.0.0-beta.x/guides/draft.md new file mode 100644 index 0000000000..16d28802c2 --- /dev/null +++ b/docs/3.0.0-beta.x/guides/draft.md @@ -0,0 +1,123 @@ +# Draft system + +This guide will explain how to create draft system. That will you manage draft, published, archive status. + +## Introduction + +What we want here is to fetch only data that have a `published` status. + +But we don't want to use [parameters](../content-api/parameters.md) (eg. /articles?status=published) because you can easily fake the params. + +To be able to do that, you have first to understand some concepts. + +When you create a content type, it generates an API with the following list of [endpoints](../content-api/endpoint.md). + +Each of these endpoint triggers a controller action. Here is the list of [controller actions](../concepts/controller.md) that exist by default when a content type is created. + +If you check the controller file of your generated API `./api/{content-type}/controller/{Content-Type}.js`, you will see an empty file. It is because all the default logic is managed by Strapi. But you can override these actions with your own code. + +And that is what we will do to filter to `published` status by default. + +## Example + +In our example we will use an Article content type. By default when you fetch articles, you will got all articles. +Let's consider you don't want to expose articles that are in `draft` or `archive` status. + +To enforce this rule we will customize the action that fetchs all articles to just fetch `published` articles. + +To follow the example your will have to create a content type `articles` and add the following field definition: + +- `string` attribute named `title` +- `text` attribute named `content` +- `enumeration` attribute named `status` with `draft`, `published`, `archive` + +Then add some data with different `status`. + +## Override controller action + +To customize the function that fetch all our articles we will have to override the `find` function. + +First, to see the difference, let's request `GET /articles`. You will see all the data you created. +Now let's start the customization. + +**Path —** `./api/article/controller/Article.js` + +```js +module.exports = { + async find() { + return 'strapi'; + }, +}; +``` + +After saving the new function, let's restart the `GET /articles` request. We will see `strapi` as response. + +## Get the data back + +We now know the function we have to update, but we just want to customize the returned article values. + +In the [controller documentation](../concepts/controllers.html#extending-a-model-controller) you will find the default implementation of every actions. It will help you overwrite the fetch logic. + +**Path —** `./api/article/controller/Article.js` + +```js +const { sanitizeEntity } = require('strapi-utils'); + +module.exports = { + async find(ctx) { + let entities; + if (ctx.query._q) { + entities = await strapi.services.article.search(ctx.query); + } else { + entities = await strapi.services.article.find(ctx.query); + } + + return entities.map(entity => + sanitizeEntity(entity, { model: strapi.models.article }) + ); + }, +}; +``` + +And now the data is back on `GET /articles` + +## Apply our changes + +Here we want force to fetch articles that have status equal to `published`. + +The way to do that is to set `ctx.query.status` to `published`. +It will force the filter of the query. + +**Path —** `./api/restaurant/controller/Restaurant.js` + +```js +const { sanitizeEntity } = require('strapi-utils'); + +module.exports = { + async find(ctx) { + let entities; + + ctx.query = { + ...ctx.query, + status: 'published + }; + + if (ctx.query._q) { + entities = await strapi.services.article.search(ctx.query); + } else { + entities = await strapi.services.article.find(ctx.query); + } + + return entities.map(entity => + sanitizeEntity(entity, { model: strapi.models.article }) + ); + }, +}; +``` + +And tada! Draft and archived articles disapeared. + +::: tip +This guide can be applied to any other controller action. +::: + diff --git a/docs/3.0.0-beta.x/plugins/upload.md b/docs/3.0.0-beta.x/plugins/upload.md index 090eb04c64..2cd257ee06 100644 --- a/docs/3.0.0-beta.x/plugins/upload.md +++ b/docs/3.0.0-beta.x/plugins/upload.md @@ -76,7 +76,7 @@ You have to send FormData in your request body ## Upload files related to an entry -To upload files that will be liked to an specific entry. +To upload files that will be linked to an specific entry. ### Request parameters diff --git a/packages/strapi-connector-bookshelf/lib/queries.js b/packages/strapi-connector-bookshelf/lib/queries.js index fb102b13fd..95bc45d6d7 100644 --- a/packages/strapi-connector-bookshelf/lib/queries.js +++ b/packages/strapi-connector-bookshelf/lib/queries.js @@ -134,7 +134,7 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) { if (Object.keys(relations).length > 0) { return model.updateRelations( - Object.assign(params, { values: relations }), + { id: entry.id, values: relations }, { transacting: trx } ); } @@ -774,8 +774,8 @@ const buildSearchQuery = (qb, model, params) => { case 'pg': { const searchQuery = searchText.map(attribute => _.toLower(attribute) === attribute - ? `to_tsvector(${attribute})` - : `to_tsvector("${attribute}")` + ? `to_tsvector(coalesce(${attribute}, ''))` + : `to_tsvector(coalesce("${attribute}", ''))` ); qb.orWhereRaw(`${searchQuery.join(' || ')} @@ plainto_tsquery(?)`, query); diff --git a/packages/strapi-connector-bookshelf/lib/utils/attributes.js b/packages/strapi-connector-bookshelf/lib/utils/attributes.js index 90f92de8a5..089b831d88 100644 --- a/packages/strapi-connector-bookshelf/lib/utils/attributes.js +++ b/packages/strapi-connector-bookshelf/lib/utils/attributes.js @@ -1,5 +1,7 @@ 'use strict'; +const { get } = require('lodash'); + /** * Returns the attribute keys of the component related attributes */ @@ -9,8 +11,10 @@ function getComponentAttributes(definition) { ); } -const isComponent = (def, key) => - ['component', 'dynamiczone'].includes(def.attributes[key].type); +const isComponent = (def, key) => { + const type = get(def, ['attributes', key, 'type']); + return ['component', 'dynamiczone'].includes(type); +}; module.exports = { getComponentAttributes, diff --git a/packages/strapi-generate-model/templates/mongoose/model.template b/packages/strapi-generate-model/templates/mongoose/model.template index 300dc5a200..30172b433f 100644 --- a/packages/strapi-generate-model/templates/mongoose/model.template +++ b/packages/strapi-generate-model/templates/mongoose/model.template @@ -6,11 +6,11 @@ module.exports = { // Before saving a value. - // Fired before an `insert` or `update` query. + // Fired before an `insert`. // beforeSave: async (model) => {}, // After saving a value. - // Fired after an `insert` or `update` query. + // Fired after an `insert`. // afterSave: async (model, result) => {}, // Before fetching all values. diff --git a/packages/strapi-generate-new/lib/resources/files/public/index.html b/packages/strapi-generate-new/lib/resources/files/public/index.html index fe5a57bec1..315cadcfbe 100644 --- a/packages/strapi-generate-new/lib/resources/files/public/index.html +++ b/packages/strapi-generate-new/lib/resources/files/public/index.html @@ -5,6 +5,7 @@ Welcome to your Strapi app + diff --git a/packages/strapi-generate-new/lib/resources/files/public/production.html b/packages/strapi-generate-new/lib/resources/files/public/production.html index 5875a7270b..3db9e22cde 100644 --- a/packages/strapi-generate-new/lib/resources/files/public/production.html +++ b/packages/strapi-generate-new/lib/resources/files/public/production.html @@ -5,6 +5,7 @@ Welcome to your Strapi app + diff --git a/packages/strapi-plugin-upload/documentation/1.0.0/overrides/upload-File.json b/packages/strapi-plugin-upload/documentation/1.0.0/overrides/upload-File.json index 4621bb93ad..52e508d305 100644 --- a/packages/strapi-plugin-upload/documentation/1.0.0/overrides/upload-File.json +++ b/packages/strapi-plugin-upload/documentation/1.0.0/overrides/upload-File.json @@ -30,7 +30,7 @@ "type": "string" }, "size": { - "type": "integer" + "type": "decimal" }, "url": { "type": "string", @@ -233,7 +233,7 @@ "type": "string" }, "size": { - "type": "string" + "type": "decimal" }, "mime": { "type": "string" @@ -260,4 +260,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-upload/models/File.settings.json b/packages/strapi-plugin-upload/models/File.settings.json index 06c270b8fe..de69fdfb21 100644 --- a/packages/strapi-plugin-upload/models/File.settings.json +++ b/packages/strapi-plugin-upload/models/File.settings.json @@ -32,7 +32,7 @@ "required": true }, "size": { - "type": "string", + "type": "decimal", "configurable": false, "required": true }, @@ -56,4 +56,4 @@ "configurable": false } } -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-upload/test/upload.test.e2e.js b/packages/strapi-plugin-upload/test/upload.test.e2e.js index aedeaa1271..249eaffcb9 100644 --- a/packages/strapi-plugin-upload/test/upload.test.e2e.js +++ b/packages/strapi-plugin-upload/test/upload.test.e2e.js @@ -132,7 +132,7 @@ describe('Upload plugin end to end tests', () => { id: expect.anything(), sha256: expect.any(String), hash: expect.any(String), - size: expect.any(String), + size: expect.any(Number), url: expect.any(String), provider: 'local', name: 'rec.jpg', diff --git a/packages/strapi-plugin-users-permissions/config/policies/permissions.js b/packages/strapi-plugin-users-permissions/config/policies/permissions.js index 55ae6bf4ad..7a32c6bfc2 100644 --- a/packages/strapi-plugin-users-permissions/config/policies/permissions.js +++ b/packages/strapi-plugin-users-permissions/config/policies/permissions.js @@ -16,13 +16,14 @@ module.exports = async (ctx, next) => { if (isAdmin) { ctx.state.admin = await strapi .query('administrator', 'admin') - .findOne({ id }); + .findOne({ id }, ['role']); } else { ctx.state.user = await strapi .query('user', 'users-permissions') - .findOne({ id }); + .findOne({ id }, ['role']); } } catch (err) { + strapi.log.error(err); return handleErrors(ctx, err, 'unauthorized'); }