Merge branch 'master' into fix-filter-doc

This commit is contained in:
Jim LAURIE 2018-02-09 20:25:32 +01:00 committed by GitHub
commit bde677735b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 551 additions and 138 deletions

View File

@ -33,6 +33,23 @@ The following types are currently available:
- `json`
- `email`
#### Validations
You can apply basic validations to the attributes. The following supported validations are *only supported by MongoDB* connection.
If you're using SQL databases, you should use the native SQL constraints to apply them.
- `required` (boolean) — if true adds a required validator for this property.
- `unique` (boolean) — whether to define a unique index on this property.
- `max` (integer) — checks if the value is greater than or equal to the given minimum.
- `min` (integer) — checks if the value is less than or equal to the given maximum.
**Security validations**
To improve the Developer eXperience when developing or using the administration panel, the framework enhances the attributes with these "security validations":
- `private` (boolean) — if true, the attribute will be removed from the server response (it's useful to hide sensitive data).
- `configurable` (boolean) - if false, the attribute isn't configurable from the Content Type Builder plugin.
#### Example
**Path —** `User.settings.json`.
@ -50,14 +67,23 @@ The following types are currently available:
"lastname": {
"type": "string"
},
"email": {
"type": "email",
"required": true,
"unique": true
},
"password": {
"type": "password"
"type": "password",
"required": true,
"private": true
},
"about": {
"type": "description"
},
"age": {
"type": "integer"
"type": "integer",
"min": 18,
"max": 99
},
"birthday": {
"type": "date"

View File

@ -71,7 +71,8 @@
flex-shrink: 0;
width: 144px;
height: 144px;
border: 1px solid #E8EEFC;
background: #FAFAFB;
border: 1px solid #F3F3F7;
border-radius: 3px;
background-size: contain;
line-height: 144px;

View File

@ -41,7 +41,7 @@ function LeftMenuLinkContainer({ plugins }) {
<p className={styles.title}>{pluginsSections[current].name}</p>
<ul className={styles.list}>
{sortBy(pluginsSections[current].links, 'label').map((link, i) =>
<LeftMenuLink key={`${i}-${link.label}`} icon={link.icon || 'link'} label={link.label} destination={`/plugins/${link.plugin}/${link.destination}`} source={link.source} />
<LeftMenuLink key={`${i}-${link.label}`} icon={link.icon || 'caret-right'} label={link.label} destination={`/plugins/${link.plugin}/${link.destination}`} source={link.source} />
)}
</ul>
</div>
@ -79,12 +79,12 @@ function LeftMenuLinkContainer({ plugins }) {
<p className={styles.title}><FormattedMessage {...messages.general} /></p>
<ul className={styles.list}>
<LeftMenuLink
icon="puzzle-piece"
icon="list"
label={messages.listPlugins.id}
destination="/list-plugins"
/>
<LeftMenuLink
icon="download"
icon="shopping-basket"
label={messages.installNewPlugin.id}
destination="/install-plugin"
/>

View File

@ -1,15 +1,15 @@
{
"listPlugins": {
"id": "app.components.LeftMenuLinkContainer.listPlugins",
"defaultMessage": "List plugins"
"defaultMessage": "Plugins"
},
"installNewPlugin": {
"id": "app.components.LeftMenuLinkContainer.installNewPlugin",
"defaultMessage": "Install new plugin"
"defaultMessage": "Marketplace"
},
"configuration": {
"id": "app.components.LeftMenuLinkContainer.configuration",
"defaultMessage": "Configuration"
"defaultMessage": "Configurations"
},
"plugins": {
"id": "app.components.LeftMenuLinkContainer.plugins",

View File

@ -86,13 +86,11 @@ class PluginCard extends React.Component {
buttonLabel = 'app.components.PluginCard.Button.label.support';
}
const pluginIcon = this.props.plugin.id !== 'email' ? (
const pluginIcon = (
<div className={styles.frame}>
<span className={styles.helper} />
<img src={`${this.props.plugin.logo}`} alt="icon" />
</div>
) : (
<div className={styles.iconContainer}><i className={`fa fa-${this.props.plugin.icon}`} /></div>
);
const descriptions = {

View File

@ -88,7 +88,8 @@
height: 36px;
margin: auto 0;
text-align: center;
border: 1px solid #E8EEFC;
background: #FAFAFB;
border: 1px solid #F3F3F7;
border-radius: 3px;
white-space: nowrap;
> img {
@ -101,7 +102,8 @@
height: 36px;
width: 70px;
margin-right: 14px;
border: 1px solid #E8EEFC;
background: #FAFAFB;
border: 1px solid #F3F3F7;
border-radius: 3px;
text-align: center;
font-size: 20px;

View File

@ -8,7 +8,8 @@
position: relative;
margin: auto 0;
text-align: center;
border: 1px solid rgba(28,93,231,0.1);
background: #FAFAFB;
border: 1px solid #F3F3F7;
border-radius: 3px;
font-size: 20px;

File diff suppressed because one or more lines are too long

View File

@ -11,8 +11,8 @@
"app.components.HomePage.button": "Create your first content type",
"app.components.HomePage.feedback": "Feel free to ask questions or give us feedback by using one of the support channels below.",
"app.components.InstallPluginPage.helmet": "Install plugins",
"app.components.InstallPluginPage.title": "Install new plugins",
"app.components.InstallPluginPage.helmet": "Marketplace - Plugins",
"app.components.InstallPluginPage.title": "Marketplace - Plugins",
"app.components.InstallPluginPage.description": "Extend your app with no efforts",
"app.components.InstallPluginPage.plugin.support-us.description": "Support us by buying the Strapi t-shirt. It will allow us to keep working on the project and try giving the best possible experience!",
"app.components.InstallPluginPage.InputSearch.label": " ",
@ -26,10 +26,10 @@
"app.components.InstallPluginPopup.noDescription": "No description available",
"app.components.LeftMenuFooter.poweredBy": "Proudly powered by",
"app.components.LeftMenuLinkContainer.configuration": "Configuration",
"app.components.LeftMenuLinkContainer.configuration": "Configurations",
"app.components.LeftMenuLinkContainer.general": "General",
"app.components.LeftMenuLinkContainer.installNewPlugin": "Install new plugin",
"app.components.LeftMenuLinkContainer.listPlugins": "List plugins",
"app.components.LeftMenuLinkContainer.installNewPlugin": "Marketplace",
"app.components.LeftMenuLinkContainer.listPlugins": "Plugins",
"app.components.LeftMenuLinkContainer.noPluginsInstalled": "No plugins installed yet",
"app.components.LeftMenuLinkContainer.plugins": "Plugins",

View File

@ -11,8 +11,8 @@
"app.components.HomePage.button": "Créez votre premier type de contenu",
"app.components.HomePage.feedback": "N'hésitez pas à utiliser un des channels ci-dessous pour poser vos questions ou nous donner vos retours.",
"app.components.InstallPluginPage.helmet": "Installez des plugins",
"app.components.InstallPluginPage.title": "Installez des nouveaux plugins",
"app.components.InstallPluginPage.helmet": "Marketplace - Plugins",
"app.components.InstallPluginPage.title": "Marketplace - Plugins",
"app.components.InstallPluginPage.description": "Améliorez votre app sans efforts",
"app.components.InstallPluginPage.plugin.support-us.description": "Soutenez-nous en achetant un Strapi tee shirt. Cela nous aidera a continuer de travailler sur le projet pour vous donner la meilleure expérience possible!",
"app.components.InstallPluginPage.InputSearch.label": " ",
@ -26,10 +26,10 @@
"app.components.InstallPluginPopup.noDescription": "Aucune description disponible",
"app.components.LeftMenuFooter.poweredBy": "Propulsé par",
"app.components.LeftMenuLinkContainer.configuration": "Configuration",
"app.components.LeftMenuLinkContainer.configuration": "Configurations",
"app.components.LeftMenuLinkContainer.general": "Général",
"app.components.LeftMenuLinkContainer.installNewPlugin": "Installer un nouveau plugin",
"app.components.LeftMenuLinkContainer.listPlugins": "Liste des plugins",
"app.components.LeftMenuLinkContainer.installNewPlugin": "Marketplaces",
"app.components.LeftMenuLinkContainer.listPlugins": "Plugins",
"app.components.LeftMenuLinkContainer.noPluginsInstalled": "Aucun plugin installé",
"app.components.LeftMenuLinkContainer.plugins": "Plugins",

View File

@ -28,6 +28,10 @@ module.exports = {
*/
findOne: async (ctx) => {
if (!ctx.params._id.match(/^[0-9a-fA-F]{24}$/)) {
return ctx.notFound();
}
const data = await strapi.services.<%= id %>.fetch(ctx.params);
// Send 200 `ok`

View File

@ -1,5 +1,5 @@
{
"timeout": 1000,
"timeout": 3000,
"load": {
"order": [
"Define the hooks' load order by putting their names in this array in the right order"

View File

@ -29,6 +29,7 @@ const logger = require('strapi-utils').logger;
module.exports = (scope, cb) => {
// App info.
const hasDatabaseConfig = !!scope.database;
_.defaults(scope, {
name: scope.name === '.' || !scope.name ? scope.name : path.basename(process.cwd()),
author: process.env.USER || 'A Strapi developer',
@ -116,7 +117,6 @@ module.exports = (scope, cb) => {
}
])
.then(answers => {
if (hasDatabaseConfig) {
const databaseChoice = _.find(databaseChoices, ['value.database', scope.database.settings.client]);
scope.database.connector = databaseChoice.value.connector;
@ -186,10 +186,11 @@ module.exports = (scope, cb) => {
},
{
when: !hasDatabaseConfig,
type: 'input',
type: 'password',
prefix: '',
name: 'password',
message: 'Password:',
mask: '*',
default: _.get(scope.database, 'password', undefined)
}
])

View File

@ -208,7 +208,10 @@ InputNumberWithErrors.propTypes = {
style: PropTypes.object,
tabIndex: PropTypes.string,
validations: PropTypes.object,
value: PropTypes.string.isRequired,
value: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),
};
export default InputNumberWithErrors;

View File

@ -86,7 +86,7 @@ class InputSelectWithErrors extends React.Component {
disabled={disabled}
error={!isEmpty(this.state.errors)}
name={name}
onBlur={onBlur}
onBlur={isFunction(onBlur) ? onBlur : () => {}}
onChange={onChange}
onFocus={onFocus}
selectOptions={selectOptions}
@ -167,7 +167,10 @@ InputSelectWithErrors.propTypes = {
labelClassName: PropTypes.string,
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
onBlur: PropTypes.func,
onBlur: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.func,
]),
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func,
selectOptions: PropTypes.arrayOf(

View File

@ -1 +1 @@
<svg width="35" height="24" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M1.148 20.03c.567-7.141 2.974-7.675 7.222-1.604 6.372 9.107 7.533-.667 9.19-2.017" stroke="#FFD2B6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><g fill-rule="nonzero"><path d="M21.313 16.48l1.081-1.082-2.792-2.792-1.081 1.081v1.271h1.52v1.521h1.272zm6.214-11.027c0-.174-.087-.26-.262-.26a.275.275 0 0 0-.202.082l-6.44 6.44a.275.275 0 0 0-.082.202c0 .174.087.261.261.261.08 0 .147-.028.202-.083l6.44-6.44a.275.275 0 0 0 .083-.202zm-.642-2.28l4.943 4.942L21.943 18H17v-4.943l9.885-9.885zM35 4.312c0 .42-.147.776-.44 1.07l-1.972 1.971-4.942-4.942 1.972-1.96A1.412 1.412 0 0 1 30.688 0c.419 0 .78.15 1.08.451l2.792 2.78c.293.31.44.67.44 1.082z" fill="#181D29"/><path d="M35 4.313c0 .42-.147.776-.44 1.07l-1.972 1.971-4.942-4.942 1.972-1.96A1.412 1.412 0 0 1 30.688 0c.419 0 .78.15 1.08.451l2.792 2.78c.293.31.44.67.44 1.082z" fill="#FF84B3"/></g></g></svg>
<svg width="30" height="24" xmlns="http://www.w3.org/2000/svg"><text transform="translate(-20 -6)" fill="#4B515A" fill-rule="evenodd" font-size="30" font-family="AppleColorEmoji, Apple Color Emoji"><tspan x="20" y="31">📖</tspan></text></svg>

Before

Width:  |  Height:  |  Size: 980 B

After

Width:  |  Height:  |  Size: 244 B

View File

@ -1 +1 @@
<svg width="22" height="22" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M8.604.607c.317.623.75 1.155 1.298 1.597.549.443 1.16.754 1.835.934l.012.873c.032 1.745-.494 3.166-1.579 4.264-1.084 1.098-2.5 1.647-4.247 1.647-1 0-1.885-.19-2.657-.571a4.852 4.852 0 0 1-1.858-1.567 7.325 7.325 0 0 1-1.055-2.25A9.927 9.927 0 0 1 0 2.832l.5.369c.276.205.528.387.755.547.228.16.468.309.72.448.251.14.438.21.56.21.333 0 .557-.152.67-.455a6.33 6.33 0 0 1 .701-1.383c.264-.381.547-.692.847-.934.3-.242.658-.436 1.073-.584A6.547 6.547 0 0 1 7.08.736c.422-.062.93-.105 1.523-.13z" id="a"/></defs><g fill="none" fill-rule="evenodd"><g transform="translate(0 12)"><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><use fill="#EABE8D" fill-rule="nonzero" xlink:href="#a"/><path d="M10.18.264c4.086 6.335 2.315 9.584-5.314 9.747-7.629.163-6.185-1.797 4.331-5.88l.982-3.867z" fill="#DB1818" mask="url(#b)"/><path d="M10.564.16C11.422 6.26 8.9 9.507 2.998 9.904c-5.902.397-4.484-1.392 4.255-5.367L10.563.16z" fill="#F1D520" mask="url(#b)"/><path d="M10.196-1.556C9.168 5.281 6.272 8.728 1.507 8.786c-4.764.059-3.209-1.83 4.668-5.663l4.021-4.679z" fill="#32B167" mask="url(#b)"/><path d="M9.506-4.516C9.417 2.713 6.99 6.357 2.226 6.414-2.539 6.474-.784 4.262 7.49-.22l2.016-4.295z" fill="#1279EA" mask="url(#b)"/><path d="M9.449-4.392C8.72 1.871 5.974 5.032 1.209 5.09c-4.764.058-3.398-1.712 4.099-5.311l4.14-4.17z" fill="#4C2DCE" mask="url(#b)"/></g><path d="M19.88 0c.564 0 1.058.186 1.482.56.424.372.635.84.635 1.401 0 .505-.181 1.111-.544 1.817-2.679 5.045-4.555 8.06-5.628 9.047-.783.73-1.662 1.095-2.638 1.095-1.017 0-1.89-.37-2.62-1.113-.73-.742-1.096-1.622-1.096-2.64 0-1.027.371-1.877 1.113-2.551L18.306.65c.476-.433 1-.65 1.573-.65z" fill-rule="nonzero" fill="#553D38"/></g></svg>
<svg width="30" height="30" xmlns="http://www.w3.org/2000/svg"><text transform="translate(-19 -4)" fill="#4B515A" fill-rule="evenodd" font-size="30" font-family="AppleColorEmoji, Apple Color Emoji"><tspan x="19" y="32">🏭</tspan></text></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 244 B

View File

@ -8,7 +8,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { isEmpty, map, findIndex } from 'lodash';
import { FormattedMessage } from 'react-intl';
import Input from 'components/Input';
import Input from 'components/InputsIndex';
import styles from './styles.scss';
class InputCheckboxWithNestedInputs extends React.Component { // eslint-disable-line react/prefer-stateless-function
@ -69,7 +69,7 @@ class InputCheckboxWithNestedInputs extends React.Component { // eslint-disable-
<div className={`${styles.inputCheckboxWithNestedInputs} col-md-12`}>
<div className="form-check" style={{ zIndex: '9999' }}>
{title}
<FormattedMessage id={this.props.data.label}>
<FormattedMessage id={this.props.data.label.id}>
{(message) => (
<label className={`${styles.checkboxLabel} form-check-label`} htmlFor={this.props.data.name} style={{ cursor: 'pointer' }}>
<input

View File

@ -9,13 +9,45 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { get, map, includes, split, isEmpty, findIndex } from 'lodash';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import Input from 'components/Input';
import Input from 'components/InputsIndex';
import PopUpHeaderNavLink from 'components/PopUpHeaderNavLink';
import styles from './styles.scss';
/* eslint-disable react/jsx-wrap-multilines */
class PopUpForm extends React.Component { // eslint-disable-line react/prefer-stateless-function
createComponent = (el) => {
if (get(el, ['inputDescription', 'params', 'link', 'children', 'type'], '') === 'FormattedMessage') {
return (
<FormattedMessage id={get(el, ['inputDescription', 'params', 'link', 'children', 'attr', 'id'], 'default')} defaultMessage=" ">
{(message) => (
React.createElement(
// Create the wrapper component
// This line will create the link
get(el, ['inputDescription', 'params', 'link', 'parent', 'type'], 'span'),
// Set the attributes
get(el, ['inputDescription', 'params', 'link', 'parent', 'attr'], ''),
message,
)
)}
</FormattedMessage>
);
}
return (
React.createElement(
get(el, ['inputDescription', 'params', 'link', 'parent', 'type'], 'span'),
// Set the attributes
get(el, ['inputDescription', 'params', 'link', 'parent', 'attr'], ''),
React.createElement(
get(el, ['inputDescription', 'params', 'link', 'children', 'type'], 'span'),
get(el, ['inputDescription', 'params', 'link', 'children', 'attr'], ''),
get(el, ['inputDescription', 'params', 'link', 'children', 'innerHTML'], ''),
)
)
);
}
renderInput = (item, key) => {
// const customBootstrapClass = 'col-md-6'
let customBootstrapClass = item.type === 'textarea' ?
@ -36,6 +68,12 @@ class PopUpForm extends React.Component { // eslint-disable-line react/prefer-st
const handleBlur = shouldOverrideHandleBlur ? this.props.onBlur : false;
const errorIndex = findIndex(this.props.formErrors, ['name', item.name]);
const errors = errorIndex !== -1 ? this.props.formErrors[errorIndex].errors : [];
const inputDescription = {
id: get(item, ['inputDescription', 'id'], ''),
params: {
link: this.createComponent(item),
},
};
return (
<Input
@ -46,7 +84,7 @@ class PopUpForm extends React.Component { // eslint-disable-line react/prefer-st
label={item.label}
name={item.name}
validations={item.validations}
inputDescription={item.inputDescription}
inputDescription={inputDescription}
value={value}
customBootstrapClass={customBootstrapClass}
selectOptions={this.props.selectOptions || []}
@ -54,8 +92,6 @@ class PopUpForm extends React.Component { // eslint-disable-line react/prefer-st
title={item.title}
errors={errors}
didCheckErrors={this.props.didCheckErrors}
pluginID={this.props.pluginID}
linkContent={item.linkContent}
autoFocus={key === 0}
/>
);
@ -159,7 +195,6 @@ PopUpForm.propTypes = {
PropTypes.bool,
PropTypes.func,
]),
pluginID: PropTypes.string,
popUpHeaderNavLinks: PropTypes.array,
popUpTitle: PropTypes.string.isRequired,
renderCustomPopUpHeader: PropTypes.oneOfType([
@ -189,7 +224,6 @@ PopUpForm.defaultProps = {
overrideHandleBlurCondition: false,
overrideRenderInput: false,
overrideRenderInputCondition: false,
pluginID: 'content-type-builder',
popUpHeaderNavLinks: [],
renderCustomPopUpHeader: false,
routePath: '',

View File

@ -10,7 +10,7 @@ import { findIndex, get, isEmpty, map, take, takeRight } from 'lodash';
import { FormattedMessage } from 'react-intl';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import Input from 'components/Input';
import Input from 'components/InputsIndex';
import PopUpHeaderNavLink from 'components/PopUpHeaderNavLink';
import RelationBox from 'components/RelationBox';
import RelationNaturePicker from 'components/RelationNaturePicker';

View File

@ -11,7 +11,7 @@ import { get, isEmpty, map, startCase } from 'lodash';
import pluralize from 'pluralize';
import { ButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
import Input from 'components/Input';
import Input from 'components/InputsIndex';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-static-element-interactions */

View File

@ -3,7 +3,9 @@
"baseSettings": {
"items": [
{
"label": "content-type-builder.form.contentType.item.connections",
"label": {
"id": "content-type-builder.form.contentType.item.connections"
},
"name": "connection",
"type": "select",
"value": "default",
@ -13,21 +15,40 @@
}
},
{
"label": "content-type-builder.form.contentType.item.name",
"label": {
"id": "content-type-builder.form.contentType.item.name"
},
"name": "name",
"value": "",
"type": "string",
"validations": {
"required": true
},
"inputDescription": "content-type-builder.form.contentType.item.name.description",
"linkContent": {
"description": "content-type-builder.form.contentType.item.name.link.description",
"link": "https://v3.strapi.io/documentation/concepts/concepts.html#models"
"inputDescription": {
"id": "content-type-builder.form.contentType.item.name.description",
"params": {
"link": {
"parent": {
"type": "a",
"attr": {
"href": "https://v3.strapi.io/documentation/concepts/concepts.html#models",
"target": "_blank"
}
},
"children": {
"type": "FormattedMessage",
"attr": {
"id": "content-type-builder.form.contentType.item.name.link.description"
}
}
}
}
}
},
{
"label": "content-type-builder.form.contentType.item.description",
"label": {
"id": "content-type-builder.form.contentType.item.description"
},
"name": "description",
"value": "",
"type": "textarea",
@ -39,12 +60,16 @@
"advancedSettings": {
"items": [
{
"label": "content-type-builder.form.contentType.item.collectionName",
"label": {
"id": "content-type-builder.form.contentType.item.collectionName"
},
"name": "collectionName",
"type": "string",
"value": "",
"validations": {},
"inputDescription": "content-type-builder.form.contentType.item.collectionName.inputDescription"
"inputDescription": {
"id": "content-type-builder.form.contentType.item.collectionName.inputDescription"
}
}
]
}
@ -94,7 +119,9 @@
"baseSettings": {
"items": [
{
"label": "content-type-builder.form.attribute.item.textarea.name",
"label": {
"id": "content-type-builder.form.attribute.item.textarea.name"
},
"name": "name",
"type": "string",
"value": "",
@ -107,24 +134,36 @@
"advancedSettings": {
"items": [
{
"title": "content-type-builder.form.attribute.item.settings.name",
"label": "content-type-builder.form.attribute.item.requiredField",
"title": {
"id": "content-type-builder.form.attribute.item.settings.name"
},
"label": {
"id": "content-type-builder.form.attribute.item.requiredField"
},
"name": "params.required",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.requiredField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.requiredField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.uniqueField",
"label": {
"id": "content-type-builder.form.attribute.item.uniqueField"
},
"name": "params.unique",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.uniqueField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.uniqueField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.minimumLength",
"label": {
"id": "content-type-builder.form.attribute.item.minimumLength"
},
"name": "params.minLength",
"type": "checkbox",
"value": false,
@ -142,7 +181,9 @@
]
},
{
"label": "content-type-builder.form.attribute.item.maximumLength",
"label": {
"id": "content-type-builder.form.attribute.item.maximumLength"
},
"name": "params.maxLength",
"type": "checkbox",
"value": false,
@ -166,7 +207,9 @@
"baseSettings": {
"items": [
{
"label": "content-type-builder.form.attribute.item.number.name",
"label": {
"id": "content-type-builder.form.attribute.item.number.name"
},
"name": "name",
"type": "string",
"value": "",
@ -175,7 +218,9 @@
}
},
{
"label": "content-type-builder.form.attribute.item.number.type",
"label": {
"id": "content-type-builder.form.attribute.item.number.type"
},
"name": "params.type",
"type": "select",
"value": "integer",
@ -193,24 +238,36 @@
"advancedSettings": {
"items": [
{
"title": "content-type-builder.form.attribute.item.settings.name",
"label": "content-type-builder.form.attribute.item.requiredField",
"title": {
"id": "content-type-builder.form.attribute.item.settings.name"
},
"label": {
"id": "content-type-builder.form.attribute.item.requiredField"
},
"name": "params.required",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.requiredField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.requiredField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.uniqueField",
"label": {
"id": "content-type-builder.form.attribute.item.uniqueField"
},
"name": "params.unique",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.uniqueField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.uniqueField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.minimum",
"label": {
"id": "content-type-builder.form.attribute.item.minimum"
},
"name": "params.min",
"type": "checkbox",
"value": false,
@ -228,7 +285,9 @@
]
},
{
"label": "content-type-builder.form.attribute.item.maximum",
"label": {
"id": "content-type-builder.form.attribute.item.maximum"
},
"name": "params.max",
"type": "checkbox",
"value": false,
@ -252,7 +311,9 @@
"baseSettings": {
"items": [
{
"label": "content-type-builder.form.attribute.item.string.name",
"label": {
"id": "content-type-builder.form.attribute.item.string.name"
},
"name": "name",
"type": "string",
"value": "",
@ -265,24 +326,36 @@
"advancedSettings": {
"items": [
{
"title": "content-type-builder.form.attribute.item.settings.name",
"label": "content-type-builder.form.attribute.item.requiredField",
"title": {
"id": "content-type-builder.form.attribute.item.settings.name"
},
"label": {
"id": "content-type-builder.form.attribute.item.requiredField"
},
"name": "params.required",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.requiredField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.requiredField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.uniqueField",
"label": {
"id": "content-type-builder.form.attribute.item.uniqueField"
},
"name": "params.unique",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.uniqueField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.uniqueField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.minimumLength",
"label": {
"id": "content-type-builder.form.attribute.item.minimumLength"
},
"name": "params.minLength",
"type": "checkbox",
"value": false,
@ -300,7 +373,9 @@
]
},
{
"label": "content-type-builder.form.attribute.item.maximumLength",
"label": {
"id": "content-type-builder.form.attribute.item.maximumLength"
},
"name": "params.maxLength",
"type": "checkbox",
"value": false,
@ -324,7 +399,9 @@
"baseSettings": {
"items": [
{
"label": "content-type-builder.form.attribute.item.string.name",
"label": {
"id": "content-type-builder.form.attribute.item.string.name"
},
"name": "name",
"type": "string",
"value": "",
@ -337,24 +414,36 @@
"advancedSettings": {
"items": [
{
"title": "content-type-builder.form.attribute.item.settings.name",
"label": "content-type-builder.form.attribute.item.requiredField",
"title": {
"id": "content-type-builder.form.attribute.item.settings.name"
},
"label": {
"id": "content-type-builder.form.attribute.item.requiredField"
},
"name": "params.required",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.requiredField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.requiredField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.uniqueField",
"label": {
"id": "content-type-builder.form.attribute.item.uniqueField"
},
"name": "params.unique",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.uniqueField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.uniqueField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.minimumLength",
"label": {
"id": "content-type-builder.form.attribute.item.minimumLength"
},
"name": "params.minLength",
"type": "checkbox",
"value": false,
@ -372,7 +461,9 @@
]
},
{
"label": "content-type-builder.form.attribute.item.maximumLength",
"label": {
"id": "content-type-builder.form.attribute.item.maximumLength"
},
"name": "params.maxLength",
"type": "checkbox",
"value": false,
@ -396,7 +487,9 @@
"baseSettings": {
"items": [
{
"label": "content-type-builder.form.attribute.item.string.name",
"label": {
"id": "content-type-builder.form.attribute.item.string.name"
},
"name": "name",
"type": "string",
"value": "",
@ -409,16 +502,24 @@
"advancedSettings": {
"items": [
{
"title": "content-type-builder.form.attribute.item.settings.name",
"label": "content-type-builder.form.attribute.item.requiredField",
"title": {
"id": "content-type-builder.form.attribute.item.settings.name"
},
"label": {
"id": "content-type-builder.form.attribute.item.requiredField"
},
"name": "params.required",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.requiredField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.requiredField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.minimumLength",
"label": {
"id": "content-type-builder.form.attribute.item.minimumLength"
},
"name": "params.minLength",
"type": "checkbox",
"value": false,
@ -436,7 +537,9 @@
]
},
{
"label": "content-type-builder.form.attribute.item.maximumLength",
"label": {
"id": "content-type-builder.form.attribute.item.maximumLength"
},
"name": "params.maxLength",
"type": "checkbox",
"value": false,
@ -460,7 +563,9 @@
"baseSettings": {
"items": [
{
"label": "content-type-builder.form.attribute.item.date.name",
"label": {
"id": "content-type-builder.form.attribute.item.date.name"
},
"name": "name",
"type": "string",
"value": "",
@ -473,21 +578,31 @@
"advancedSettings": {
"items": [
{
"title": "content-type-builder.form.attribute.item.settings.name",
"label": "content-type-builder.form.attribute.item.requiredField",
"title": {
"id": "content-type-builder.form.attribute.item.settings.name"
},
"label": {
"id": "content-type-builder.form.attribute.item.requiredField"
},
"name": "params.required",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.requiredField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.requiredField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.uniqueField",
"label": {
"id": "content-type-builder.form.attribute.item.uniqueField"
},
"name": "params.unique",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.uniqueField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.uniqueField.description"
}
}
]
}
@ -496,7 +611,9 @@
"baseSettings": {
"items": [
{
"label": "content-type-builder.form.attribute.item.boolean.name",
"label": {
"id": "content-type-builder.form.attribute.item.boolean.name"
},
"name": "name",
"type": "string",
"value": "",
@ -509,21 +626,31 @@
"advancedSettings": {
"items": [
{
"title": "content-type-builder.form.attribute.item.settings.name",
"label": "content-type-builder.form.attribute.item.requiredField",
"title": {
"id": "content-type-builder.form.attribute.item.settings.name"
},
"label": {
"id": "content-type-builder.form.attribute.item.requiredField"
},
"name": "params.required",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.requiredField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.requiredField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.uniqueField",
"label": {
"id": "content-type-builder.form.attribute.item.uniqueField"
},
"name": "params.unique",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.uniqueField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.uniqueField.description"
}
}
]
}
@ -532,7 +659,9 @@
"baseSettings": {
"items": [
{
"label": "content-type-builder.form.attribute.item.json.name",
"label": {
"id": "content-type-builder.form.attribute.item.json.name"
},
"name": "name",
"type": "string",
"value": "",
@ -545,21 +674,31 @@
"advancedSettings": {
"items": [
{
"title": "content-type-builder.form.attribute.item.settings.name",
"label": "content-type-builder.form.attribute.item.requiredField",
"title": {
"id": "content-type-builder.form.attribute.item.settings.name"
},
"label": {
"id": "content-type-builder.form.attribute.item.requiredField"
},
"name": "params.required",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.requiredField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.requiredField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.uniqueField",
"label": {
"id": "content-type-builder.form.attribute.item.uniqueField"
},
"name": "params.unique",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.uniqueField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.uniqueField.description"
}
}
]
}
@ -568,7 +707,9 @@
"baseSettings": {
"items": [
{
"label": "content-type-builder.form.attribute.item.media.name",
"label": {
"id": "content-type-builder.form.attribute.item.media.name"
},
"name": "name",
"type": "string",
"value": "",
@ -581,21 +722,31 @@
"advancedSettings": {
"items": [
{
"title": "content-type-builder.form.attribute.item.settings.name",
"label": "content-type-builder.form.attribute.item.requiredField",
"title": {
"id": "content-type-builder.form.attribute.item.settings.name"
},
"label": {
"id": "content-type-builder.form.attribute.item.requiredField"
},
"name": "params.required",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.requiredField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.requiredField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.uniqueField",
"label": {
"id": "content-type-builder.form.attribute.item.uniqueField"
},
"name": "params.unique",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.uniqueField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.uniqueField.description"
}
}
]
}
@ -604,7 +755,9 @@
"defineRelation": {
"items": [
{
"label": "content-type-builder.form.attribute.item.defineRelation.fieldName",
"label": {
"id": "content-type-builder.form.attribute.item.defineRelation.fieldName"
},
"name": "name",
"type": "string",
"value": "",
@ -614,7 +767,9 @@
}
},
{
"label": "content-type-builder.form.attribute.item.defineRelation.fieldName",
"label": {
"id": "content-type-builder.form.attribute.item.defineRelation.fieldName"
},
"name": "params.key",
"type": "string",
"value": "",
@ -628,20 +783,28 @@
"advancedSettings": {
"items": [
{
"label": "content-type-builder.form.attribute.item.uniqueField",
"label": {
"id": "content-type-builder.form.attribute.item.uniqueField"
},
"name": "params.unique",
"type": "checkbox",
"value": false,
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.uniqueField.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.uniqueField.description"
}
},
{
"label": "content-type-builder.form.attribute.item.customColumnName",
"label": {
"id": "content-type-builder.form.attribute.item.customColumnName"
},
"name": "params.columnName",
"type": "string",
"value": "",
"validations": {},
"inputDescription": "content-type-builder.form.attribute.item.customColumnName.description"
"inputDescription": {
"id": "content-type-builder.form.attribute.item.customColumnName.description"
}
},
{
"label": "",

View File

@ -70,7 +70,7 @@
"form.contentType.item.connections": "Connection",
"form.contentType.item.name": "Name",
"form.contentType.item.name.description": "Content type name's should be singular",
"form.contentType.item.name.description": "Content type name's should be singular, {link}",
"form.contentType.item.name.link.description": "check out our documentation",
"form.contentType.item.description": "Description",
"form.contentType.item.description.placeholder": "Write your little description here...",

View File

@ -72,7 +72,7 @@
"form.contentType.item.connections": "Connexion",
"form.contentType.item.name": "Nom",
"form.contentType.item.name.description": "Les noms de modèles doivent être au singulier",
"form.contentType.item.name.description": "Les noms de modèles doivent être au singulier, {link}",
"form.contentType.item.name.link.description": "regardez la documentation",
"form.contentType.item.description": "Description",
"form.contentType.item.description.placeholder": "Ecrivez votre petite description ici...",

View File

@ -79,7 +79,7 @@ module.exports = {
return new Promise((resolve, reject) => {
const scope = {
generatorType: 'api',
id: name,
id: name.toLowerCase(),
rootPath: strapi.config.appPath,
args: {
api: name,

View File

@ -0,0 +1 @@
<svg width="24" height="17" xmlns="http://www.w3.org/2000/svg"><text transform="translate(-23 -9)" fill="#4B515A" fill-rule="evenodd" font-size="24" font-family="AppleColorEmoji, Apple Color Emoji"><tspan x="23" y="28">✉️</tspan></text></svg>

After

Width:  |  Height:  |  Size: 246 B

View File

@ -1 +1 @@
<svg width="54" height="34" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g fill-rule="nonzero"><path d="M11.392 30.3a1.797 1.797 0 0 0-.22-1.409 1.797 1.797 0 0 0-1.141-.857 1.797 1.797 0 0 0-1.41.22c-.449.27-.734.65-.857 1.142-.122.492-.049.962.22 1.41.27.449.65.734 1.142.857.491.122.961.049 1.41-.22.448-.27.734-.65.856-1.142zm21.224-7.353L8.464 37.459c-.874.525-1.812.663-2.813.413-.983-.245-1.756-.809-2.318-1.692L1.09 32.37c-.548-.86-.695-1.8-.44-2.82.249-1.002.822-1.772 1.72-2.311l24.117-14.492a14.885 14.885 0 0 0 2.02 5.728 14.885 14.885 0 0 0 4.108 4.472z" fill="#181D29"/><path d="M53.663 15.097c-.184.737-.65 1.684-1.401 2.842-1.52 2.31-3.587 3.978-6.2 5.003-2.615 1.024-5.254 1.204-7.918.54-3.497-.872-6.177-2.86-8.043-5.965-1.865-3.105-2.362-6.405-1.49-9.901.871-3.496 2.86-6.177 5.964-8.043 3.105-1.865 6.405-2.362 9.901-1.49 1.096.273 2.205.715 3.328 1.326 1.122.611 2.028 1.304 2.718 2.078.251.283.336.586.256.907-.08.321-.297.548-.651.68l-9.5 2.72-1.584 6.35 4.715 4.397c.109-.033.97-.305 2.582-.816 1.613-.511 3.084-.957 4.414-1.339 1.33-.38 2.08-.55 2.25-.508.283.071.481.22.595.45.113.229.135.485.064.769z" fill="#A1A1A1"/></g><path stroke="#C6C6C6" fill="#D8D8D8" d="M46.521 5.425l3.657 3.41-1.125 4.872-4.781 1.461-3.657-3.41 1.125-4.871z"/></g></svg>
<svg width="40" height="28" xmlns="http://www.w3.org/2000/svg"><g fill="#4B515A" fill-rule="evenodd" font-family="AppleColorEmoji, Apple Color Emoji"><text font-size="14" transform="translate(0 -2)"><tspan x="0" y="27">⚙️</tspan></text><text font-size="24" transform="translate(0 -2)"><tspan x="16" y="24">⚙️</tspan></text></g></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 341 B

View File

@ -1 +1 @@
<svg width="28" height="26" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero" fill="none"><path d="M8.453 12.772c-1.54.047-2.799.656-3.778 1.824h-1.91c-.779 0-1.435-.192-1.967-.577C.266 13.634 0 13.071 0 12.33c0-3.354.59-5.032 1.768-5.032.057 0 .263.1.62.3.356.2.82.401 1.39.605.57.205 1.135.307 1.696.307.636 0 1.268-.11 1.896-.328a7.106 7.106 0 0 0-.072.94c0 1.322.385 2.538 1.155 3.65zm15.266 9.08c0 1.14-.347 2.04-1.04 2.701-.694.66-1.616.99-2.766.99H7.455c-1.15 0-2.072-.33-2.765-.99-.694-.66-1.04-1.56-1.04-2.701 0-.504.016-.995.049-1.475.033-.48.1-.998.2-1.554s.225-1.072.377-1.547c.152-.475.357-.938.613-1.39.257-.45.551-.836.884-1.154a3.718 3.718 0 0 1 1.219-.763 4.28 4.28 0 0 1 1.59-.285c.094 0 .298.102.612.307.314.204.66.432 1.04.684.38.252.89.48 1.526.684a6.264 6.264 0 0 0 1.924.307c.646 0 1.288-.103 1.925-.307.636-.204 1.145-.432 1.525-.684.38-.252.727-.48 1.04-.684.314-.205.518-.307.613-.307.58 0 1.11.095 1.59.285.48.19.886.445 1.218.763.333.318.628.703.884 1.155.257.45.461.914.613 1.39.152.474.278.99.378 1.546.1.556.166 1.074.2 1.554.033.48.05.971.05 1.475zm3.65-9.522c0 .741-.267 1.304-.799 1.69-.532.384-1.188.576-1.967.576h-1.91c-.979-1.168-2.238-1.777-3.777-1.824.77-1.112 1.154-2.328 1.154-3.65 0-.275-.024-.588-.071-.94.627.219 1.259.328 1.896.328.56 0 1.126-.102 1.696-.307a9.374 9.374 0 0 0 1.39-.605c.356-.2.563-.3.62-.3 1.178 0 1.767 1.678 1.767 5.032z" fill="#553D38"/><path d="M9.123 3.65a3.516 3.516 0 0 1-1.07 2.58 3.516 3.516 0 0 1-2.58 1.068 3.516 3.516 0 0 1-2.58-1.069 3.516 3.516 0 0 1-1.068-2.58c0-1.007.356-1.867 1.069-2.58A3.516 3.516 0 0 1 5.474 0C6.48 0 7.34.356 8.054 1.07a3.516 3.516 0 0 1 1.069 2.58zm10.035 5.473c0 1.51-.535 2.8-1.604 3.87-1.069 1.069-2.359 1.603-3.87 1.603-1.51 0-2.8-.534-3.87-1.603-1.069-1.07-1.603-2.36-1.603-3.87 0-1.511.534-2.801 1.603-3.87 1.07-1.07 2.36-1.604 3.87-1.604 1.511 0 2.801.535 3.87 1.604 1.07 1.069 1.604 2.359 1.604 3.87zm6.386-5.474a3.516 3.516 0 0 1-1.07 2.58 3.516 3.516 0 0 1-2.58 1.07 3.516 3.516 0 0 1-2.58-1.07 3.516 3.516 0 0 1-1.068-2.58c0-1.007.356-1.867 1.069-2.58A3.516 3.516 0 0 1 21.895 0c1.007 0 1.867.356 2.58 1.07a3.516 3.516 0 0 1 1.069 2.58z" fill="#EBBF8E"/><path d="M12.496 19.991h2.393v-.897c0-.33-.117-.612-.35-.846a1.153 1.153 0 0 0-.847-.35c-.33 0-.612.116-.846.35-.233.234-.35.516-.35.846v.897zm3.889.45v2.691c0 .125-.044.231-.131.318a.433.433 0 0 1-.318.131h-4.487a.433.433 0 0 1-.318-.13.433.433 0 0 1-.131-.319V20.44c0-.124.044-.23.13-.318a.433.433 0 0 1 .319-.13h.15v-.898c0-.573.205-1.066.616-1.477A2.015 2.015 0 0 1 13.692 17c.574 0 1.066.206 1.477.617.412.411.617.904.617 1.477v.897h.15c.125 0 .23.044.318.131.087.088.13.194.13.318z" fill="#FFF"/></g></svg>
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg"><text transform="translate(-24 -6)" fill="#4B515A" fill-rule="evenodd" font-size="24" font-family="AppleColorEmoji, Apple Color Emoji"><tspan x="24" y="28">🔐</tspan></text></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 244 B

View File

@ -86,7 +86,7 @@
"HeaderNav.link.providers": "Providers",
"HeaderNav.link.roles": "Roles",
"HomePage.header.title": "Auth & Permissions",
"HomePage.header.title": "Users & Permissions",
"HomePage.header.description": "Define the roles and permissions for every one of them",
"InputSearch.placeholder": "Search for a user",

View File

@ -86,7 +86,7 @@
"HeaderNav.link.providers": "Fournisseurs",
"HeaderNav.link.roles": "Rôles",
"HomePage.header.title": "Auth & Permissions",
"HomePage.header.title": "Utilisateurs & Permissions",
"HomePage.header.description": "Définissez les rôles et permissions pour chacun d'eux",
"InputSearch.placeholder": "Recherez un utilisateur",

View File

@ -8,7 +8,6 @@
const _ = require('lodash');
const crypto = require('crypto');
const Grant = require('grant-koa');
const emailRegExp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
module.exports = {
@ -65,7 +64,7 @@ module.exports = {
return ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: 'Auth.form.error.invalid' }] }] : 'Identifier or password invalid.');
} else {
ctx.send({
jwt: strapi.plugins['users-permissions'].services.jwt.issue(user),
jwt: strapi.plugins['users-permissions'].services.jwt.issue(_.pick(user.toJSON ? user.toJSON() : user, ['_id', 'id'])),
user: _.omit(user.toJSON ? user.toJSON() : user, ['password', 'resetPasswordToken'])
});
}
@ -87,7 +86,7 @@ module.exports = {
}
ctx.send({
jwt: strapi.plugins['users-permissions'].services.jwt.issue(user),
jwt: strapi.plugins['users-permissions'].services.jwt.issue(_.pick(user, ['_id', 'id'])),
user: _.omit(user.toJSON ? user.toJSON() : user, ['password', 'resetPasswordToken'])
});
}
@ -112,7 +111,7 @@ module.exports = {
await strapi.query('user', 'users-permissions').update(user);
ctx.send({
jwt: strapi.plugins['users-permissions'].services.jwt.issue(user),
jwt: strapi.plugins['users-permissions'].services.jwt.issue(_.pick(user.toJSON ? user.toJSON() : user, ['_id', 'id'])),
user: _.omit(user.toJSON ? user.toJSON() : user, ['password', 'resetPasswordToken'])
});
} else if (params.password && params.passwordConfirmation && params.password !== params.passwordConfirmation) {
@ -137,6 +136,7 @@ module.exports = {
return ctx.badRequest(null, 'This provider is disabled.');
}
const Grant = require('grant-koa');
const grant = new Grant(strapi.plugins['users-permissions'].config.grant);
return strapi.koaMiddlewares.compose(grant.middleware)(ctx, next);
@ -250,7 +250,7 @@ module.exports = {
const user = await strapi.query('user', 'users-permissions').create(params);
ctx.send({
jwt: strapi.plugins['users-permissions'].services.jwt.issue(user),
jwt: strapi.plugins['users-permissions'].services.jwt.issue(_.pick(user.toJSON ? user.toJSON() : user, ['_id', 'id'])),
user: _.omit(user.toJSON ? user.toJSON() : user, ['password', 'resetPasswordToken'])
});
} catch(err) {

View File

@ -25,11 +25,13 @@
"password": {
"type": "password",
"minLength": 6,
"configurable": false
"configurable": false,
"private": true
},
"resetPasswordToken": {
"type": "string",
"configurable": false
"configurable": false,
"private": true
},
"role": {
"model": "role",

View File

@ -3,7 +3,7 @@
"version": "3.0.0-alpha.9.3",
"description": "Protect your API with a full-authentication process based on JWT",
"strapi": {
"name": "Auth & Permissions",
"name": "Users & Permissions",
"icon": "users",
"description": "users-permissions.plugin.description"
},

View File

@ -42,7 +42,15 @@ module.exports = function (name, cliArguments) {
developerMode
};
if (_.values(_.omit(cliArguments, ['dev'])).length) {
const dbArguments = ['dbclient', 'dbhost', 'dbport', 'dbname', 'dbusername', 'dbpassword'];
const matchingDbArguments = _.intersection(_.keys(cliArguments), dbArguments);
if (matchingDbArguments.length) {
if (matchingDbArguments.length !== dbArguments.length) {
logger.warn(`Some database arguments are missing. Required arguments list: ${dbArguments}`);
return process.exit(1);
}
scope.database = {
settings: {
client: cliArguments.dbclient,

View File

@ -244,6 +244,9 @@ module.exports.app = async function() {
boom: {
enabled: true
},
mask: {
enabled: true
},
// Necessary middlewares for the administration panel.
cors: {
enabled: true

View File

@ -0,0 +1,5 @@
{
"mask": {
"enabled": false
}
}

View File

@ -0,0 +1,158 @@
'use strict';
/**
* Module dependencies
*/
/**
* Mask filter middleware
*/
const _ = require('lodash');
module.exports = strapi => {
return {
/**
* Initialize the hook
*/
initialize: function (cb) {
// Enable the middleware if we need it.
const enabled = (() => {
const main = Object.keys(strapi.models).reduce((acc, current) => {
if (Object.values(strapi.models[current].attributes).find(attr => attr.private === true)) {
acc = true;
}
return acc;
}, false);
const plugins = Object.keys(strapi.plugins).reduce((acc, plugin) => {
const bool = Object.keys(strapi.plugins[plugin].models).reduce((acc, model) => {
if (Object.values(strapi.plugins[plugin].models[model].attributes).find(attr => attr.private === true)) {
acc = true;
}
return acc;
}, false);
if (bool) {
acc = true;
}
return acc;
}, false);
return main || plugins;
})();
if (enabled) {
strapi.app.use(async (ctx, next) => {
// Execute next middleware.
await next();
// Recursive to mask the private properties.
const mask = (payload) => {
if (_.isArray(payload)) {
return payload.map(mask);
} else if (_.isPlainObject(payload)) {
return this.mask(
ctx,
Object.keys(payload).reduce((acc, current) => {
acc[current] = _.isObjectLike(payload[current]) ? mask(payload[current]) : payload[current];
return acc;
}, {})
);
}
return payload;
};
// Only pick successful JSON requests.
if ([200, 201, 202].includes(ctx.status) && ctx.type === 'application/json') {
ctx.body = mask(ctx.body);
}
});
}
cb();
},
mask: function (ctx, value) {
const models = this.filteredModels(this.whichModels(value, ctx.request.route.plugin));
if (models.length === 0) {
return value;
}
const attributesToHide = models.reduce((acc, match) => {
const attributes = match.plugin ?
strapi.plugins[match.plugin].models[match.model].attributes:
strapi.models[match.model].attributes;
acc = acc.concat(Object.keys(attributes).filter(attr => attributes[attr].private === true));
return acc;
}, []);
// Hide attribute.
return _.omit(value, attributesToHide);
},
whichModels: function (value, plugin) {
const keys = Object.keys(value);
let maxMatch = 0;
let matchs = [];
const match = (model, plugin) => {
const attributes = plugin ?
Object.keys(strapi.plugins[plugin].models[model].attributes):
Object.keys(strapi.models[model].attributes);
const intersection = _.intersection(keys, attributes.filter(attr => ['id', '_id', '_v'].indexOf(attr) === -1 )).length;
// Most matched model.
if (intersection > maxMatch) {
maxMatch = intersection;
matchs = [{
plugin,
model,
intersection
}];
} else if (intersection === maxMatch && intersection > 0) {
matchs.push({
plugin,
model,
intersection
});
}
};
// Application models.
Object.keys(strapi.models).forEach(model => match(model));
// Plugins models.
Object.keys(strapi.plugins).forEach(plugin => {
Object.keys(strapi.plugins[plugin].models).forEach(model => match(model, plugin));
});
return matchs;
},
filteredModels: function (matchs) {
return matchs.reduce((acc, match, index) => {
const attributes = match.plugin ?
strapi.plugins[match.plugin].models[match.model].attributes:
strapi.models[match.model].attributes;
// Filtered model which have more than 50% of the attributes
// in common with the original model.
if (match.intersection >= Object.keys(attributes).length / 2) {
acc[index] = match;
}
return acc;
}, []);
}
};
};