Merge branch 'main' into STRAP-54

This commit is contained in:
GitStart 2022-09-06 12:30:37 +01:00 committed by GitHub
commit d3c8267cf2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 154 additions and 67 deletions

View File

@ -91,10 +91,12 @@ Complete installation requirements can be found in the documentation under <a hr
**Database:**
- MySQL >= 5.7.8
- MariaDB >= 10.2.7
- PostgreSQL >= 10
- SQLite >= 3
| Database | Minimum | Recommended |
| ---------- | ------- | ----------- |
| MySQL | 5.7.8 | 8.0 |
| MariaDB | 10.3 | 10.6 |
| PostgreSQL | 11.0 | 14.0 |
| SQLite | 3 | 3 |
**We recommend always using the latest version of Strapi to start your new projects**.

View File

@ -759,7 +759,7 @@
"global.table.header.roles": "Roles",
"global.table.header.username": "Nombre de usuario",
"global.type": "Tipo",
"global.users": "Useuarios",
"global.users": "Usuarios",
"notification.warning.404": "404 - No Encontrado"
}

View File

@ -776,7 +776,6 @@ const createEntityManager = (db) => {
}
},
// TODO: support multiple relations at once with the populate syntax
// TODO: add lifecycle events
async populate(uid, entity, populate) {
const entry = await this.findOne(uid, {
@ -788,30 +787,37 @@ const createEntityManager = (db) => {
return { ...entity, ...entry };
},
// TODO: support multiple relations at once with the populate syntax
// TODO: add lifecycle events
async load(uid, entity, field, params) {
async load(uid, entity, fields, params) {
const { attributes } = db.metadata.get(uid);
const fieldsArr = _.castArray(fields);
fieldsArr.forEach((field) => {
const attribute = attributes[field];
if (!attribute || attribute.type !== 'relation') {
throw new Error('Invalid load. Expected a relational attribute');
throw new Error(`Invalid load. Expected ${field} to be a relational attribute`);
}
});
const entry = await this.findOne(uid, {
select: ['id'],
where: { id: entity.id },
populate: {
[field]: params || true,
},
populate: fieldsArr.reduce((acc, field) => {
acc[field] = params || true;
return acc;
}, {}),
});
if (!entry) {
return null;
}
return entry[field];
if (Array.isArray(fields)) {
return _.pick(fields, entry);
}
return entry[fields];
},
// cascading

View File

@ -1,8 +1,12 @@
<p align="center">
<a href="https://strapi.io">
<a href="https://strapi.io/#gh-light-mode-only">
<img src="https://strapi.io/assets/strapi-logo-dark.svg" width="318px" alt="Strapi logo" />
</a>
<a href="https://strapi.io/#gh-dark-mode-only">
<img src="https://strapi.io/assets/strapi-logo-light.svg" width="318px" alt="Strapi logo" />
</a>
</p>
<h3 align="center">API creation made simple, secure and fast.</h3>
<p align="center">The most advanced open-source headless CMS to build powerful APIs with no effort.</p>
<p align="center"><a href="https://strapi.io/demo">Try live demo</a></p>
@ -18,6 +22,9 @@
<a href="https://discord.strapi.io">
<img src="https://img.shields.io/discord/811989166782021633?label=Discord" alt="Strapi on Discord" />
</a>
<a href="https://github.com/strapi/strapi/actions/workflows/nightly.yml">
<img src="https://github.com/strapi/strapi/actions/workflows/nightly.yml/badge.svg" alt="Strapi Nightly Release Build Status" />
</a>
</p>
<br>
@ -79,15 +86,17 @@ Complete installation requirements can be found in the documentation under <a hr
**Node:**
- NodeJS >= 12 <= 16
- NodeJS >= 14 <= 16
- NPM >= 6.x
**Database:**
- MySQL >= 5.7.8
- MariaDB >= 10.2.7
- PostgreSQL >= 10
- SQLite >= 3
| Database | Minimum | Recommended |
| ---------- | ------- | ----------- |
| MySQL | 5.7.8 | 8.0 |
| MariaDB | 10.3 | 10.6 |
| PostgreSQL | 11.0 | 14.0 |
| SQLite | 3 | 3 |
**We recommend always using the latest version of Strapi to start your new projects**.
@ -114,7 +123,7 @@ For general help using Strapi, please refer to [the official Strapi documentatio
- [Discord](https://discord.strapi.io) (For live discussion with the Community and Strapi team)
- [GitHub](https://github.com/strapi/strapi) (Bug reports, Contributions)
- [Community Forum](https://forum.strapi.io) (Questions and Discussions)
- [Roadmap & Feature Requests](https://feedback.strapi.io/)
- [Feedback section](https://feedback.strapi.io) (Roadmap, Feature requests)
- [Twitter](https://twitter.com/strapijs) (Get the news fast)
- [Facebook](https://www.facebook.com/Strapi-616063331867161)
- [YouTube Channel](https://www.youtube.com/strapi) (Learn from Video Tutorials)
@ -125,7 +134,7 @@ Follow our [migration guides](https://docs.strapi.io/developer-docs/latest/updat
## Roadmap
Check out our [roadmap](https://feedback.strapi.io/) to get informed of the latest features released and the upcoming ones. You may also give us insights and vote for a specific feature.
Check out our [roadmap](https://feedback.strapi.io) to get informed of the latest features released and the upcoming ones. You may also give us insights and vote for a specific feature.
## Documentation

View File

@ -5,6 +5,7 @@ const { has, prop, omit, toString } = require('lodash/fp');
const { contentTypes: contentTypesUtils } = require('@strapi/utils');
const { ApplicationError } = require('@strapi/utils').errors;
const { getComponentAttributes } = require('@strapi/utils').contentTypes;
const omitComponentData = (contentType, data) => {
const { attributes } = contentType;
@ -100,6 +101,18 @@ const createComponents = async (uid, data) => {
return componentBody;
};
/**
* @param {str} uid
* @param {object} entity
* @return {Promise<{uid: string, entity: object}>}
*/
const getComponents = async (uid, entity) => {
const componentAttributes = getComponentAttributes(strapi.getModel(uid));
if (_.isEmpty(componentAttributes)) return {};
return strapi.query(uid).load(entity, componentAttributes);
};
/*
delete old components
create or update
@ -270,7 +283,10 @@ const deleteComponents = async (uid, entityToDelete) => {
if (attribute.type === 'component') {
const { component: componentUID } = attribute;
const value = await strapi.query(uid).load(entityToDelete, attributeName);
// Load attribute value if it's not already loaded
const value =
entityToDelete[attributeName] ||
(await strapi.query(uid).load(entityToDelete, attributeName));
if (!value) {
continue;
@ -286,7 +302,9 @@ const deleteComponents = async (uid, entityToDelete) => {
}
if (attribute.type === 'dynamiczone') {
const value = await strapi.query(uid).load(entityToDelete, attributeName);
const value =
entityToDelete[attributeName] ||
(await strapi.query(uid).load(entityToDelete, attributeName));
if (!value) {
continue;
@ -352,7 +370,9 @@ const deleteComponent = async (uid, componentToDelete) => {
module.exports = {
omitComponentData,
getComponents,
createComponents,
updateComponents,
deleteComponents,
deleteComponent,
};

View File

@ -14,6 +14,7 @@ const uploadFiles = require('../utils/upload-files');
const {
omitComponentData,
getComponents,
createComponents,
updateComponents,
deleteComponents,
@ -213,8 +214,10 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
return null;
}
const componentsToDelete = await getComponents(uid, entityToDelete);
await db.query(uid).delete({ where: { id: entityToDelete.id } });
await deleteComponents(uid, entityToDelete);
await deleteComponents(uid, { ...entityToDelete, ...componentsToDelete });
await this.emitEvent(uid, ENTRY_DELETE, entityToDelete);
@ -234,8 +237,12 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
return null;
}
const componentsToDelete = await Promise.all(
entitiesToDelete.map((entityToDelete) => getComponents(uid, entityToDelete))
);
const deletedEntities = await db.query(uid).deleteMany(query);
await Promise.all(entitiesToDelete.map((entity) => deleteComponents(uid, entity)));
await Promise.all(componentsToDelete.map((compos) => deleteComponents(uid, compos)));
// Trigger webhooks. One for each entity
await Promise.all(entitiesToDelete.map((entity) => this.emitEvent(uid, ENTRY_DELETE, entity)));

View File

@ -158,6 +158,15 @@ describe('Core API - Basic + compo + draftAndPublish', () => {
data.productsWithCompoAndDP.shift();
});
describe('database state', () => {
test('components have been removed from the database', async () => {
const dbComponents = await strapi.db
.query('default.compo')
.findMany({ name: 'compo name updated' });
expect(dbComponents).toHaveLength(0);
});
});
describe('validation', () => {
test('Cannot create product with compo - compo required', async () => {
const product = {

View File

@ -106,6 +106,20 @@ const isPrivateAttribute = (model = {}, attributeName) => {
const isScalarAttribute = (attribute) => {
return !['media', 'component', 'relation', 'dynamiczone'].includes(attribute.type);
};
const isMediaAttribute = (attribute) => attribute.type === 'media';
const isRelationalAttribute = (attribute) => attribute.type === 'relation';
const isComponentAttribute = (attribute) => ['component', 'dynamiczone'].includes(attribute.type);
const getComponentAttributes = (schema) => {
return _.reduce(
schema.attributes,
(acc, attr, attrName) => {
if (isComponentAttribute(attr)) acc.push(attrName);
return acc;
},
[]
);
};
const getScalarAttributes = (schema) => {
return _.reduce(
@ -118,10 +132,6 @@ const getScalarAttributes = (schema) => {
);
};
const isMediaAttribute = (attribute) => attribute.type === 'media';
const isRelationalAttribute = (attribute) => attribute.type === 'relation';
const isComponentAttribute = (attribute) => ['component', 'dynamiczone'].includes(attribute.type);
/**
* Checks if an attribute is of type `type`
* @param {object} attribute
@ -152,6 +162,7 @@ module.exports = {
isPrivateAttribute,
constants,
getNonWritableAttributes,
getComponentAttributes,
getScalarAttributes,
getWritableAttributes,
isWritableAttribute,

View File

@ -102,6 +102,13 @@ paths:
tags:
- Users-Permissions - Auth
summary: Default Callback from provider auth
parameters:
- name: provider
in: path
required: true
description: Provider name
schema:
type: string
responses:
200:
description: Returns a jwt token and user info
@ -196,15 +203,16 @@ paths:
application/json:
schema:
type: object
required:
- password
- currentPassword
- passwordConfirmation
properties:
password:
required: true
type: string
currentPassword:
required: true
type: string
passwordConfirmation:
required: true
type: string
responses:
200:
@ -219,7 +227,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/email-confirmation:
get:
tags:
@ -228,6 +235,7 @@ paths:
parameters:
- in: query
name: confirmation
schema:
type: string
description: confirmation token received by email
responses:
@ -319,7 +327,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
/users-permissions/roles:
get:
tags:
@ -364,7 +371,7 @@ paths:
- Users-Permissions - Users & Roles
summary: Create a role
requestBody:
$ref: '#/components/schemas/Users-Permissions-RoleRequest'
$ref: '#/components/requestBodies/Users-Permissions-RoleRequest'
responses:
200:
description: Returns ok if the role was create
@ -391,10 +398,13 @@ paths:
parameters:
- in: path
name: id
required: true
schema:
type: string
description: role Id
responses:
200:
description: Returns the role
content:
application/json:
schema:
@ -431,10 +441,12 @@ paths:
parameters:
- in: path
name: role
required: true
schema:
type: string
description: role Id
requestBody:
$ref: '#/components/schemas/Users-Permissions-RoleRequest'
$ref: '#/components/requestBodies/Users-Permissions-RoleRequest'
responses:
200:
description: Returns ok if the role was udpated
@ -460,6 +472,8 @@ paths:
parameters:
- in: path
name: role
required: true
schema:
type: string
description: role Id
responses:
@ -487,7 +501,7 @@ paths:
summary: Get list of users
responses:
200:
summary: Returns an array of users
description: Returns an array of users
content:
application/json:
schema:
@ -520,17 +534,17 @@ paths:
application/json:
schema:
type: object
required:
- username
- email
- password
properties:
email:
type: string
required: true
username:
type: string
required: true
password:
type: string
required: true
example:
username: foo
email: foo@strapi.io
@ -569,7 +583,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
/users/{id}:
get:
tags:
@ -578,10 +591,13 @@ paths:
parameters:
- in: path
name: id
required: true
schema:
type: string
description: user Id
responses:
200:
description: Returns a user
content:
application/json:
schema:
@ -601,7 +617,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- Users-Permissions - Users & Roles
@ -609,6 +624,8 @@ paths:
parameters:
- in: path
name: id
required: true
schema:
type: string
description: user Id
requestBody:
@ -617,17 +634,17 @@ paths:
application/json:
schema:
type: object
required:
- username
- email
- password
properties:
email:
type: string
required: true
username:
type: string
required: true
password:
type: string
required: true
example:
username: foo
email: foo@strapi.io
@ -666,13 +683,19 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Users-Permissions - Users & Roles
summary: Delete a user
parameters:
- in: path
name: id
required: true
schema:
type: string
description: user Id
responses:
200:
"200":
description: Returns deleted user info
content:
application/json:
@ -817,6 +840,10 @@ components:
policy:
type: string
parameters:
responses:
examples:
requestBodies:
Users-Permissions-RoleRequest:
required: true
content:
@ -842,7 +869,3 @@ components:
find:
enabled: true
parameters:
responses:
examples:
requestBodies:

View File

@ -37,7 +37,7 @@
"test": "echo \"no tests yet\""
},
"dependencies": {
"aws-sdk": "2.1188.0",
"aws-sdk": "2.1208.0",
"lodash": "4.17.21"
},
"engines": {

View File

@ -7493,10 +7493,10 @@ available-typed-arrays@^1.0.5:
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
aws-sdk@2.1188.0:
version "2.1188.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1188.0.tgz#94b710948ef2924093a8d6fe42443a792385afa2"
integrity sha512-4KXwjRjbCzU1luTOeH+ded92H51I4UuHaZzx2EI+JA0II1+q48heTxFlFd7yp7jGz9UwjPb6k12Jv1W3r0JWxA==
aws-sdk@2.1208.0:
version "2.1208.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1208.0.tgz#7dc8c877652d2b1ea126a3c256157c1cbd2e20e2"
integrity sha512-Wyq9TJyvRZMcHmcGwmOJag5/94m+Gq3BHcK2klwFvgUf1OWWJc4OYqmi90d7qJ09ydTeGGMeodNJildQdkOrYQ==
dependencies:
buffer "4.9.2"
events "1.1.1"