Fix conflict

This commit is contained in:
cyril lopez 2017-11-29 19:00:51 +01:00
commit a7b56b484f
31 changed files with 250 additions and 1110 deletions

View File

@ -311,6 +311,10 @@ Callbacks on `fetch`:
- beforeFetch
- afterFetch
Callbacks on `fetchAll`:
- beforeFetchAll
- afterFetchAll
Callbacks on `create`:
- beforeCreate
- afterCreate
@ -334,20 +338,12 @@ module.exports = {
/**
* Triggered before user creation.
*/
beforeCreate: function (next) {
beforeCreate: async (model) => {
// Hash password.
strapi.api.user.services.user.hashPassword(this.password)
.then((passwordHashed) => {
// Set the password.
this.password = passwordHashed;
const passwordHashed = await strapi.api.user.services.user.hashPassword(this.password);
// Execute the callback.
next();
})
.catch((error) => {
next(error);
});
}
// Set the password.
model.password = passwordHashed;
}
}
```
@ -363,21 +359,12 @@ module.exports = {
/**
* Triggered before user creation.
*/
beforeCreate: function (model, attrs, options) {
return new Promise((resolve, reject) => {
beforeCreate: async (model, attrs, options) => {
// Hash password.
strapi.api.user.services.user.hashPassword(model.attributes.password)
.then((passwordHashed) => {
const passwordHashed = await strapi.api.user.services.user.hashPassword(model.attributes.password);
// Set the password.
model.set('password', passwordHashed);
// Execute the callback.
resolve();
})
.catch((error) => {
reject(error);
});
}
});
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -20,8 +20,8 @@
background-image: url('../../assets/images/logo-strapi.png');
background-repeat: no-repeat;
background-position: center center;
background-size: auto 2.5rem;
background-position: 55px 17px;
background-size: auto 3rem;
}
.leftMenuHeaderLink {

View File

@ -13,8 +13,8 @@
color: $left-menu-title-color;
text-transform: uppercase;
font-size: 1.1rem;
letter-spacing: .2rem;
font-weight: 600;
letter-spacing: .1rem;
font-weight: 800;
}
.list {

View File

@ -17,4 +17,8 @@
html {
font-size: 62.5%;
}
* {
-webkit-font-smoothing: antialiased;
}
}

View File

@ -5,81 +5,50 @@
*/
module.exports = {
// Before saving a value.
// Fired before an `insert` or `update` query.
// beforeSave: function (next) {
// // Use `this` to get your current object
// next();
// },
// beforeSave: async (model) => {},
// After saving a value.
// Fired after an `insert` or `update` query.
// afterSave: function (doc, next) {
// next();
// },
// afterSave: async (model, result) => {},
// Before fetching all values.
// Fired before a `fetchAll` operation.
// beforeFetchAll: function (next) {
// // Use `this` to get your current object
// next();
// },
// beforeFetchAll: async (model) => {},
// After fetching all values.
// Fired after a `fetchAll` operation.
// afterFetchAll: function (doc, next) {
// next();
// },
// afterFetchAll: async (model, results) => {},
// Fired before a `fetch` operation.
// beforeFetch: function (next) {
// // Use `this` to get your current object
// next();
// },
// beforeFetch: async (model) => {},
// After fetching a value.
// Fired after a `fetch` operation.
// afterFetch: function (doc, next) {
// next();
// },
// afterFetch: async (model, result) => {},
// Before creating a value.
// Fired before `insert` query.
// beforeCreate: function (next) {
// // Use `this` to get your current object
// next();
// },
// beforeCreate: async (model) => {},
// After creating a value.
// Fired after `insert` query.
// afterCreate: function (doc, next) {
// next();
// },
// afterCreate: async (model, result) => {},
// Before updating a value.
// Fired before an `update` query.
// beforeUpdate: function (next) {
// // Use `this` to get your current object
// next();
// },
// beforeUpdate: async (model) => {},
// After updating a value.
// Fired after an `update` query.
// afterUpdate: function (doc, next) {
// next();
// },
// afterUpdate: async (model, result) => {},
// Before destroying a value.
// Fired before a `delete` query.
// beforeDestroy: function (next) {
// // Use `this` to get your current object
// next();
// },
// beforeDestroy: async (model) => {},
// After destroying a value.
// Fired after a `delete` query.
// afterDestroy: function (doc, next) {
// next();
// }
// afterDestroy: async (model, result) => {}
};

View File

@ -68,7 +68,7 @@
width: 3.4rem;
height: 3.4rem;
margin-top: .9rem;
padding-left: 1.1rem;
padding-left: 0.9rem;
background-color: rgba(16, 22, 34, 0.02);
border: 1px solid #E3E9F3;
border-radius: 0.25rem;
@ -89,6 +89,10 @@
font-weight: 900;
font-family: Lato;
}
& + input {
border-left: 0px !important;
}
}
.insideInput {

View File

@ -96,7 +96,9 @@ module.exports = function (strapi) {
_.forEach(preLifecycle, (fn, key) => {
if (_.isFunction(target[model.toLowerCase()][fn])) {
collection.schema.pre(key, target[model.toLowerCase()][fn]);
collection.schema.pre(key, function (next) {
target[model.toLowerCase()][fn](this).then(next).catch(err => strapi.log.error(err));
});
}
});
@ -111,7 +113,9 @@ module.exports = function (strapi) {
_.forEach(postLifecycle, (fn, key) => {
if (_.isFunction(target[model.toLowerCase()][fn])) {
collection.schema.post(key, target[model.toLowerCase()][fn]);
collection.schema.post(key, function (doc, next) {
target[model.toLowerCase()][fn](this, doc).then(next).catch(err => strapi.log.error(err))
});
}
});

View File

@ -51,10 +51,10 @@ class EditForm extends React.Component {
render() {
const source = getQueryParameters(this.props.location.search, 'source');
const currentSchema = get(this.props.schema, [this.props.currentModelName]) || get(this.props.schema, ['plugins', source, this.props.currentModelName]);
const currentLayout = get(this.props.layout, [this.props.currentModelName]);
const currentLayout = get(this.props.layout, [this.props.currentModelName, 'attributes']);
// Remove `id` field
const displayedFields = merge(currentLayout, omit(currentSchema.fields, 'id'));
const displayedFields = merge(get(currentLayout), omit(currentSchema.fields, 'id'));
// List fields inputs
const fields = Object.keys(displayedFields).map(attr => {

View File

@ -122,7 +122,6 @@ export class Edit extends React.Component {
componentWillReceiveProps(nextProps) {
if (this.props.editSuccess !== nextProps.editSuccess) {
if (!isEmpty(this.props.location.search)) {
strapi.notification.success('content-manager.success.record.save');
router.push(replace(this.props.location.search, '?redirectUrl=', ''));
} else {
router.push(replace(this.props.location.pathname, 'create', ''));

View File

@ -71,6 +71,8 @@ export function* editRecord(action) {
params,
});
console.log(recordCleaned);
yield put(recordEdited());
strapi.notification.success('content-manager.success.record.save');
} catch (err) {

View File

@ -21,24 +21,27 @@ import {
SET_CURRENT_MODEL_NAME,
} from './constants';
export function changeLimit(limit) {
export function changeLimit(limit, source) {
return {
type: CHANGE_LIMIT,
limit,
limit: limit <= 0 ? 20 : limit,
source,
};
}
export function changePage(page) {
export function changePage(page, source) {
return {
type: CHANGE_PAGE,
page,
page: page <= 0 ? 1 : page,
source,
};
}
export function changeSort(sort) {
export function changeSort(sort, source) {
return {
type: CHANGE_SORT,
sort,
source,
};
}

View File

@ -66,6 +66,7 @@ export class List extends React.Component {
this.state = {
showWarning: false,
source: getQueryParameters(props.location.search, 'source'),
};
}
@ -82,7 +83,7 @@ export class List extends React.Component {
}
if (!isEmpty(nextProps.location.search) && this.props.location.search !== nextProps.location.search) {
this.props.loadRecords();
this.props.loadRecords(this.state.source);
}
}
@ -91,60 +92,56 @@ export class List extends React.Component {
// Set current model name
this.props.setCurrentModelName(slug.toLowerCase());
const source = getQueryParameters(props.location.search, 'source');
const sort = (isEmpty(props.location.search) ?
get(this.props.models, ['models', slug.toLowerCase(), 'primaryKey']) || get(this.props.models.plugins, [source, 'models', slug.toLowerCase(), 'primaryKey']) :
get(this.props.models, ['models', slug.toLowerCase(), 'primaryKey']) || get(this.props.models.plugins, [this.state.source, 'models', slug.toLowerCase(), 'primaryKey']) :
getQueryParameters('sort')) || 'id';
if (!isEmpty(props.location.search)) {
this.props.changePage(toInteger(getQueryParameters('page')));
this.props.changeLimit(toInteger(getQueryParameters('limit')));
this.props.changePage(toInteger(getQueryParameters('page')), this.state.source);
this.props.changeLimit(toInteger(getQueryParameters('limit')), this.state.source);
}
this.props.changeSort(sort);
this.props.changeSort(sort, this.state.source);
// Load records
this.props.loadRecords(source);
this.props.loadRecords(this.state.source);
// Get the records count
this.props.loadCount(source);
this.props.loadCount(this.state.source);
// Define the `create` route url
this.addRoute = `${this.props.match.path.replace(':slug', slug)}/create`;
}
handleChangeLimit = ({ target }) => {
this.props.changeLimit(parseInt(target.value));
this.props.changeLimit(toInteger(target.value), this.state.source);
router.push({
pathname: this.props.location.pathname,
search: `?page=${this.props.currentPage}&limit=${target.value}&sort=${this.props.sort}`,
search: `?page=${this.props.currentPage}&limit=${target.value}&sort=${this.props.sort}&source=${this.state.source}`,
});
}
handleChangePage = (page) => {
router.push({
pathname: this.props.location.pathname,
search: `?page=${page}&limit=${this.props.limit}&sort=${this.props.sort}`,
search: `?page=${page}&limit=${this.props.limit}&sort=${this.props.sort}&source=${this.state.source}`,
});
this.props.changePage(page);
this.props.changePage(page, this.state.source);
}
handleChangeSort = (sort) => {
router.push({
pathname: this.props.location.pathname,
search: `?page=${this.props.currentPage}&limit=${this.props.limit}&sort=${sort}`,
search: `?page=${this.props.currentPage}&limit=${this.props.limit}&sort=${sort}&source=${this.state.source}`,
});
this.props.changeSort(sort);
this.props.changeSort(sort, this.state.source);
}
handleDelete = (e) => {
e.preventDefault();
e.stopPropagation();
const source = getQueryParameters(this.props.location.search, 'source');
this.props.deleteRecord(this.state.target, this.props.currentModelName, source);
this.props.deleteRecord(this.state.target, this.props.currentModelName, this.state.source);
this.setState({ showWarning: false });
}
@ -162,9 +159,8 @@ export class List extends React.Component {
render() {
// Detect current model structure from models list
const source = getQueryParameters(this.props.location.search, 'source');
const currentModel = get(this.props.models, ['models', this.props.currentModelName]) || get(this.props.models, ['plugins', source, 'models', this.props.currentModelName]);
const currentSchema = get(this.props.schema, [this.props.currentModelName]) || get(this.props.schema, ['plugins', source, this.props.currentModelName]);
const currentModel = get(this.props.models, ['models', this.props.currentModelName]) || get(this.props.models, ['plugins', this.state.source, 'models', this.props.currentModelName]);
const currentSchema = get(this.props.schema, [this.props.currentModelName]) || get(this.props.schema, ['plugins', this.state.source, this.props.currentModelName]);
if (!this.props.currentModelName || !currentSchema) {
return <div />;
@ -190,7 +186,7 @@ export class List extends React.Component {
history={this.props.history}
primaryKey={currentModel.primaryKey || 'id'}
handleDelete={this.toggleModalWarning}
redirectUrl={`?redirectUrl=/plugins/content-manager/${this.props.currentModelName.toLowerCase()}/?page=${this.props.currentPage}&limit=${this.props.limit}&sort=${this.props.sort}&source=${source}`}
redirectUrl={`?redirectUrl=/plugins/content-manager/${this.props.currentModelName.toLowerCase()}/?page=${this.props.currentPage}&limit=${this.props.limit}&sort=${this.props.sort}&source=${this.state.source}`}
/>
);
@ -205,7 +201,10 @@ export class List extends React.Component {
entity: pluginHeaderTitle,
},
kind: 'primaryAddShape',
onClick: () => this.context.router.history.push(this.addRoute),
onClick: () => this.context.router.history.push({
pathname: this.addRoute,
search: `?source=${this.state.source}`,
}),
},
];

View File

@ -0,0 +1,16 @@
const _ = require('lodash');
module.exports = async (ctx, next) => {
const { source } = ctx.request.query;
if (source && _.get(strapi.plugins, [source, 'config', 'layout', ctx.params.model, 'actions', ctx.request.route.action])) {
const [ controller, action ] = _.get(strapi.plugins, [source, 'config', 'layout', ctx.params.model, 'actions', ctx.request.route.action], []).split('.');
if (controller && action) {
// Redirect to specific controller.
return await strapi.plugins[source].controllers[controller.toLowerCase()][action](ctx);
}
}
await next();
};

View File

@ -13,7 +13,7 @@
"path": "/explorer/:model",
"handler": "ContentManager.find",
"config": {
"policies": []
"policies": ["routing"]
}
},
{
@ -21,7 +21,7 @@
"path": "/explorer/:model/count",
"handler": "ContentManager.count",
"config": {
"policies": []
"policies": ["routing"]
}
},
{
@ -29,14 +29,14 @@
"path": "/explorer/:model/:id",
"handler": "ContentManager.findOne",
"config": {
"policies": []
"policies": ["routing"]
}
},{
"method": "POST",
"path": "/explorer/:model",
"handler": "ContentManager.create",
"config": {
"policies": []
"policies": ["routing"]
}
},
{
@ -44,7 +44,7 @@
"path": "/explorer/:model/:id",
"handler": "ContentManager.update",
"config": {
"policies": []
"policies": ["routing"]
}
},
{
@ -52,7 +52,7 @@
"path": "/explorer/:model/:id",
"handler": "ContentManager.delete",
"config": {
"policies": []
"policies": ["routing"]
}
}
]

View File

@ -13,7 +13,7 @@
}
.controller {
padding: 0 28px;
padding: 1px 28px 0;
background: #ffffff;
opacity: none;
-webkit-font-smoothing: antialiased;

View File

@ -17,11 +17,11 @@
&:before {
content: '\F002';
display: inline-table;
margin-top: .2rem;
margin-left: .1rem;
margin-top: 0px;
margin-left: 2px;
color: #B3B5B9;
font-weight: 400;
font-size: 13px;
font-size: 14px;
font-family: 'FontAwesome';
-webkit-font-smoothing: antialiased;
}

View File

@ -43,7 +43,6 @@
.controllerContainer {
margin-top: 1px;
> div:not(:first-child) {
padding-top: 2.3rem;
}

View File

@ -80,8 +80,8 @@
"InputSearch.placeholder": "Search for a user",
"List.button.roles": "Add a New Role",
"List.button.providers": "Add a New Provider",
"List.button.roles": "Add New Role",
"List.button.providers": "Add New Provider",
"List.title.emailTemplates.singular": "{number} email template is available",
"List.title.emailTemplates.plural": "{number} email templates are available",

View File

@ -1,5 +1,11 @@
module.exports = {
user: {
actions: {
create: 'User.create', // Use the User plugin's controller.
update: 'User.update',
destroy: 'User.destroy'
},
attributes: {
username: {
className: 'col-md-6'
},
@ -19,4 +25,5 @@ module.exports = {
className: 'd-none'
}
}
}
};

View File

@ -41,205 +41,39 @@ module.exports = {
},
create: async function (params) {
const entry = await this
return this
.forge()
.save(Object.keys(params.values).reduce((acc, current) => {
.save(Object.keys(params).reduce((acc, current) => {
if (_.get(this, ['_attributes', current, 'type'])) {
acc[current] = params.values[current];
acc[current] = params[current];
}
return acc;
}, {}));
return module.exports.update.call(this, {
[this.primaryKey]: entry[this.primaryKey],
values: _.merge({
id: entry[this.primaryKey]
}, params.values)
});
},
update: async function (params) {
const virtualFields = [];
const response = await module.exports.findOne.call(this, params);
// Only update fields which are on this document.
const values = params.parseRelationships === false ? params.values : Object.keys(JSON.parse(JSON.stringify(params.values))).reduce((acc, current) => {
const association = this.associations.filter(x => x.alias === current)[0];
const details = this._attributes[current];
if (_.get(this._attributes, `${current}.isVirtual`) !== true && _.isUndefined(association)) {
acc[current] = params.values[current];
} else {
switch (association.nature) {
case 'oneToOne':
if (response[current] !== params.values[current]) {
const value = _.isNull(params.values[current]) ? response[current] : params.values;
const recordId = _.isNull(params.values[current]) ? value[this.primaryKey] || value.id || value._id : value[current];
if (response[current] && _.isObject(response[current]) && response[current][this.primaryKey] !== value[current]) {
virtualFields.push(
strapi.query(details.collection || details.model).update({
id: response[current][this.primaryKey],
values: {
[details.via]: null
},
parseRelationships: false
})
);
if (_.get(params, '_id')) {
params.id = params._id;
delete params._id;
}
// Remove previous relationship asynchronously if it exists.
virtualFields.push(
strapi.query(details.model || details.collection).findOne({ id : recordId })
.then(record => {
if (record && _.isObject(record[details.via])) {
return module.exports.update.call(this, {
id: record[details.via][this.primaryKey] || record[details.via].id,
values: {
[current]: null
},
parseRelationships: false
});
}
return Promise.resolve();
})
);
// Update the record on the other side.
// When params.values[current] is null this means that we are removing the relation.
virtualFields.push(strapi.query(details.model || details.collection).update({
id: recordId,
values: {
[details.via]: _.isNull(params.values[current]) ? null : value[this.primaryKey] || value.id || value._id
},
parseRelationships: false
}));
acc[current] = _.isNull(params.values[current]) ? null : value[current];
}
break;
case 'oneToMany':
case 'manyToOne':
case 'manyToMany':
if (details.dominant === true) {
acc[current] = params.values[current];
} else if (response[current] && _.isArray(response[current]) && current !== 'id') {
// Records to add in the relation.
const toAdd = _.differenceWith(params.values[current], response[current], (a, b) =>
a[this.primaryKey].toString() === b[this.primaryKey].toString()
);
// Records to remove in the relation.
const toRemove = _.differenceWith(response[current], params.values[current], (a, b) =>
a[this.primaryKey].toString() === b[this.primaryKey].toString()
)
.filter(x => toAdd.find(y => x.id === y.id) === undefined);
// Push the work into the flow process.
toAdd.forEach(value => {
value[details.via] = params.values[this.primaryKey] || params[this.primaryKey];
virtualFields.push(strapi.query(details.model || details.collection).addRelation({
id: value[this.primaryKey] || value.id || value._id,
values: association.nature === 'manyToMany' ? params.values : value,
foreignKey: current
}));
});
toRemove.forEach(value => {
value[details.via] = null;
virtualFields.push(strapi.query(details.model || details.collection).removeRelation({
id: value[this.primaryKey] || value.id || value._id,
values: association.nature === 'manyToMany' ? params.values : value,
foreignKey: current
}));
});
} else if (_.get(this._attributes, `${current}.isVirtual`) !== true) {
acc[current] = params.values[current];
}
break;
default:
}
}
return acc;
}, {});
if (!_.isEmpty(values)) {
virtualFields.push(this
.forge({
return this.forge({
[this.primaryKey]: params[this.primaryKey]
})
.save(values, {
.save(params, {
patch: true
}));
} else {
virtualFields.push(Promise.resolve(_.assign(response, params.values)));
}
// Update virtuals fields.
const process = await Promise.all(virtualFields);
return process[process.length - 1];
});
},
delete: async function (params) {
return await this
.forge({
[this.primaryKey]: params.id
[this.primaryKey]: params._id
})
.destroy();
},
addRelation: async function (params) {
const association = this.associations.filter(x => x.via === params.foreignKey)[0];
if (!association) {
// Resolve silently.
return Promise.resolve();
}
switch (association.nature) {
case 'oneToOne':
case 'oneToMany':
return module.exports.update.call(this, params);
case 'manyToMany':
return this.forge({
[this.primaryKey]: params[this.primaryKey]
})[association.alias]().attach(params.values[this.primaryKey]);
default:
// Resolve silently.
return Promise.resolve();
}
},
removeRelation: async function (params) {
const association = this.associations.filter(x => x.via === params.foreignKey)[0];
if (!association) {
// Resolve silently.
return Promise.resolve();
}
switch (association.nature) {
case 'oneToOne':
case 'oneToMany':
return module.exports.update.call(this, params);
case 'manyToMany':
return this.forge({
[this.primaryKey]: params[this.primaryKey]
})[association.alias]().detach(params.values[this.primaryKey]);
default:
// Resolve silently.
return Promise.resolve();
}
},
search: async function (params) {
return this
.query(function(qb) {

View File

@ -22,174 +22,31 @@ module.exports = {
},
create: async function (params) {
const entry = await this.create(Object.keys(params.values).reduce((acc, current) => {
return this.create(Object.keys(params).reduce((acc, current) => {
if (_.get(this._attributes, [current, 'type'])) {
acc[current] = params.values[current];
acc[current] = params[current];
}
return acc;
}, {}));
await module.exports.update.call(this, {
[this.primaryKey]: entry[this.primaryKey],
values: _.merge({
id: entry[this.primaryKey]
}, params.values)
});
return entry;
},
update: async function (params) {
const virtualFields = [];
const response = await module.exports.findOne.call(this, params);
// Only update fields which are on this document.
const values = params.parseRelationships === false ? params.values : Object.keys(JSON.parse(JSON.stringify(params.values))).reduce((acc, current) => {
const association = this.associations.filter(x => x.alias === current)[0];
const details = this._attributes[current];
if (_.get(this._attributes, `${current}.isVirtual`) !== true && _.isUndefined(association)) {
acc[current] = params.values[current];
} else {
switch (association.nature) {
case 'oneToOne':
if (response[current] !== params.values[current]) {
const value = _.isNull(params.values[current]) ? response[current] : params.values;
const recordId = _.isNull(params.values[current]) ? value[this.primaryKey] || value.id || value._id : value[current];
if (response[current] && _.isObject(response[current]) && response[current][this.primaryKey] !== value[current]) {
virtualFields.push(
strapi.query(details.collection || details.model).update({
id: response[current][this.primaryKey],
values: {
[details.via]: null
},
parseRelationships: false
})
);
}
// Remove previous relationship asynchronously if it exists.
virtualFields.push(
strapi.query(details.model || details.collection).findOne({ id : recordId })
.then(record => {
if (record && _.isObject(record[details.via])) {
return module.exports.update.call(this, {
id: record[details.via][this.primaryKey] || record[details.via].id,
values: {
[current]: null
},
parseRelationships: false
});
}
return Promise.resolve();
})
);
// Update the record on the other side.
// When params.values[current] is null this means that we are removing the relation.
virtualFields.push(strapi.query(details.model || details.collection).update({
id: recordId,
values: {
[details.via]: _.isNull(params.values[current]) ? null : value[this.primaryKey] || value.id || value._id
},
parseRelationships: false
}));
acc[current] = _.isNull(params.values[current]) ? null : value[current];
}
break;
case 'oneToMany':
case 'manyToOne':
case 'manyToMany':
if (details.dominant === true) {
acc[current] = params.values[current];
} else if (response[current] && _.isArray(response[current]) && current !== 'id') {
// Records to add in the relation.
const toAdd = _.differenceWith(params.values[current], response[current], (a, b) =>
a[this.primaryKey].toString() === b[this.primaryKey].toString()
);
// Records to remove in the relation.
const toRemove = _.differenceWith(response[current], params.values[current], (a, b) =>
a[this.primaryKey].toString() === b[this.primaryKey].toString()
)
.filter(x => toAdd.find(y => x.id === y.id) === undefined);
// Push the work into the flow process.
toAdd.forEach(value => {
if (association.nature === 'manyToMany' && !_.isArray(params.values[this.primaryKey] || params[this.primaryKey])) {
value[details.via] = (value[details.via] || []).concat([(params.values[this.primaryKey] || params[this.primaryKey])]).filter(x => {
return x !== null && x !== undefined;
});
} else {
value[details.via] = params[this.primaryKey] || params.id;
}
virtualFields.push(strapi.query(details.model || details.collection).addRelation({
id: value[this.primaryKey] || value.id || value._id,
values: value,
foreignKey: current
}));
});
toRemove.forEach(value => {
if (association.nature === 'manyToMany' && !_.isArray(params.values[this.primaryKey])) {
value[details.via] = value[details.via].filter(x => x.toString() !== params.values[this.primaryKey].toString());
} else {
value[details.via] = null;
}
virtualFields.push(strapi.query(details.model || details.collection).removeRelation({
id: value[this.primaryKey] || value.id || value._id,
values: value,
foreignKey: current
}));
});
} else if (_.get(this._attributes, `${current}.isVirtual`) !== true) {
acc[current] = params.values[current];
}
break;
default:
}
}
return acc;
}, {});
virtualFields.push(this
.update({
return this.update({
[this.primaryKey]: params[this.primaryKey] || params.id
}, values, {
}, params, {
strict: false
}));
// Update virtuals fields.
const process = await Promise.all(virtualFields);
return process[process.length - 1];
});
},
delete: async function (params) {
// Delete entry.
return this
.remove({
[this.primaryKey]: params.id
[this.primaryKey]: params[this.primaryKey] || params.id
});
},
addRelation: async function (params) {
return module.exports.update.call(this, params);
},
removeRelation: async function (params) {
return module.exports.update.call(this, params);
},
search: async function (params) {
const re = new RegExp(params.id);

View File

@ -2,585 +2,11 @@
"0": {
"description": "",
"name": "Administrator",
"permissions": {
"application": {
"controllers": {
"bite": {
"find": {
"enabled": true,
"policy": ""
},
"findOne": {
"enabled": true,
"policy": ""
},
"create": {
"enabled": true,
"policy": ""
},
"update": {
"enabled": true,
"policy": ""
},
"destroy": {
"enabled": true,
"policy": ""
},
"createRelation": {
"enabled": true,
"policy": ""
},
"updateRelation": {
"enabled": true,
"policy": ""
},
"destroyRelation": {
"enabled": true,
"policy": ""
},
"identity": {
"enabled": true,
"policy": ""
}
}
}
},
"content-manager": {
"controllers": {
"contentmanager": {
"models": {
"enabled": true,
"policy": ""
},
"find": {
"enabled": true,
"policy": ""
},
"count": {
"enabled": true,
"policy": ""
},
"findOne": {
"enabled": true,
"policy": ""
},
"create": {
"enabled": true,
"policy": ""
},
"update": {
"enabled": true,
"policy": ""
},
"delete": {
"enabled": true,
"policy": ""
},
"identity": {
"enabled": true,
"policy": ""
}
}
}
},
"content-type-builder": {
"controllers": {
"contenttypebuilder": {
"getModels": {
"enabled": true,
"policy": ""
},
"getModel": {
"enabled": true,
"policy": ""
},
"getConnections": {
"enabled": true,
"policy": ""
},
"createModel": {
"enabled": true,
"policy": ""
},
"updateModel": {
"enabled": true,
"policy": ""
},
"deleteModel": {
"enabled": true,
"policy": ""
},
"autoReload": {
"enabled": true,
"policy": ""
},
"checkTableExists": {
"enabled": true,
"policy": ""
},
"identity": {
"enabled": true,
"policy": ""
}
}
}
},
"settings-manager": {
"controllers": {
"settingsmanager": {
"menu": {
"enabled": true,
"policy": ""
},
"environments": {
"enabled": true,
"policy": ""
},
"languages": {
"enabled": true,
"policy": ""
},
"databases": {
"enabled": true,
"policy": ""
},
"database": {
"enabled": true,
"policy": ""
},
"databaseModel": {
"enabled": true,
"policy": ""
},
"get": {
"enabled": true,
"policy": ""
},
"update": {
"enabled": true,
"policy": ""
},
"createLanguage": {
"enabled": true,
"policy": ""
},
"deleteLanguage": {
"enabled": true,
"policy": ""
},
"createDatabase": {
"enabled": true,
"policy": ""
},
"updateDatabase": {
"enabled": true,
"policy": ""
},
"deleteDatabase": {
"enabled": true,
"policy": ""
},
"autoReload": {
"enabled": true,
"policy": ""
},
"identity": {
"enabled": true,
"policy": ""
}
}
}
},
"users-permissions": {
"controllers": {
"auth": {
"callback": {
"enabled": true,
"policy": ""
},
"register": {
"enabled": true,
"policy": ""
},
"forgotPassword": {
"enabled": true,
"policy": ""
},
"changePassword": {
"enabled": true,
"policy": ""
},
"identity": {
"enabled": true,
"policy": ""
}
},
"user": {
"find": {
"enabled": true,
"policy": ""
},
"findOne": {
"enabled": true,
"policy": ""
},
"create": {
"enabled": true,
"policy": ""
},
"update": {
"enabled": true,
"policy": ""
},
"destroy": {
"enabled": true,
"policy": ""
},
"identity": {
"enabled": true,
"policy": ""
}
},
"userspermissions": {
"createRole": {
"enabled": true,
"policy": ""
},
"deleteProvider": {
"enabled": true,
"policy": ""
},
"deleteRole": {
"enabled": true,
"policy": ""
},
"getPermissions": {
"enabled": true,
"policy": ""
},
"getRole": {
"enabled": true,
"policy": ""
},
"getRoles": {
"enabled": true,
"policy": ""
},
"index": {
"enabled": true,
"policy": ""
},
"init": {
"enabled": true,
"policy": ""
},
"searchUsers": {
"enabled": true,
"policy": ""
},
"updateRole": {
"enabled": true,
"policy": ""
},
"identity": {
"enabled": true,
"policy": ""
}
}
}
}
}
"permissions": {}
},
"1": {
"description": "",
"name": "Guest",
"permissions": {
"application": {
"controllers": {
"bite": {
"find": {
"enabled": false,
"policy": ""
},
"findOne": {
"enabled": false,
"policy": ""
},
"create": {
"enabled": false,
"policy": ""
},
"update": {
"enabled": false,
"policy": ""
},
"destroy": {
"enabled": false,
"policy": ""
},
"createRelation": {
"enabled": false,
"policy": ""
},
"updateRelation": {
"enabled": false,
"policy": ""
},
"destroyRelation": {
"enabled": false,
"policy": ""
},
"identity": {
"enabled": false,
"policy": ""
}
}
}
},
"content-manager": {
"controllers": {
"contentmanager": {
"models": {
"enabled": true,
"policy": ""
},
"find": {
"enabled": false,
"policy": ""
},
"count": {
"enabled": false,
"policy": ""
},
"findOne": {
"enabled": false,
"policy": ""
},
"create": {
"enabled": false,
"policy": ""
},
"update": {
"enabled": false,
"policy": ""
},
"delete": {
"enabled": false,
"policy": ""
},
"identity": {
"enabled": false,
"policy": ""
}
}
}
},
"content-type-builder": {
"controllers": {
"contenttypebuilder": {
"getModels": {
"enabled": false,
"policy": ""
},
"getModel": {
"enabled": false,
"policy": ""
},
"getConnections": {
"enabled": false,
"policy": ""
},
"createModel": {
"enabled": false,
"policy": ""
},
"updateModel": {
"enabled": false,
"policy": ""
},
"deleteModel": {
"enabled": false,
"policy": ""
},
"autoReload": {
"enabled": false,
"policy": ""
},
"checkTableExists": {
"enabled": false,
"policy": ""
},
"identity": {
"enabled": false,
"policy": ""
}
}
}
},
"settings-manager": {
"controllers": {
"settingsmanager": {
"menu": {
"enabled": false,
"policy": ""
},
"environments": {
"enabled": false,
"policy": ""
},
"languages": {
"enabled": false,
"policy": ""
},
"databases": {
"enabled": false,
"policy": ""
},
"database": {
"enabled": false,
"policy": ""
},
"databaseModel": {
"enabled": false,
"policy": ""
},
"get": {
"enabled": false,
"policy": ""
},
"update": {
"enabled": false,
"policy": ""
},
"createLanguage": {
"enabled": false,
"policy": ""
},
"deleteLanguage": {
"enabled": false,
"policy": ""
},
"createDatabase": {
"enabled": false,
"policy": ""
},
"updateDatabase": {
"enabled": false,
"policy": ""
},
"deleteDatabase": {
"enabled": false,
"policy": ""
},
"autoReload": {
"enabled": false,
"policy": ""
},
"identity": {
"enabled": false,
"policy": ""
}
}
}
},
"users-permissions": {
"controllers": {
"auth": {
"callback": {
"enabled": true,
"policy": ""
},
"register": {
"enabled": true,
"policy": ""
},
"forgotPassword": {
"enabled": false,
"policy": ""
},
"changePassword": {
"enabled": false,
"policy": ""
},
"identity": {
"enabled": false,
"policy": ""
}
},
"user": {
"find": {
"enabled": false,
"policy": ""
},
"findOne": {
"enabled": false,
"policy": ""
},
"create": {
"enabled": false,
"policy": ""
},
"update": {
"enabled": false,
"policy": ""
},
"destroy": {
"enabled": false,
"policy": ""
},
"identity": {
"enabled": false,
"policy": ""
}
},
"userspermissions": {
"createRole": {
"enabled": false,
"policy": ""
},
"deleteProvider": {
"enabled": false,
"policy": ""
},
"deleteRole": {
"enabled": false,
"policy": ""
},
"getPermissions": {
"enabled": false,
"policy": ""
},
"getRole": {
"enabled": false,
"policy": ""
},
"getRoles": {
"enabled": false,
"policy": ""
},
"index": {
"enabled": false,
"policy": ""
},
"init": {
"enabled": true,
"policy": ""
},
"searchUsers": {
"enabled": false,
"policy": ""
},
"updateRole": {
"enabled": false,
"policy": ""
},
"identity": {
"enabled": false,
"policy": ""
}
}
}
}
}
"permissions": {}
}
}

View File

@ -32,6 +32,14 @@
"policies": []
}
},
{
"method": "GET",
"path": "/policies",
"handler": "UsersPermissions.getPolicies",
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/roles/:id",

View File

@ -41,6 +41,7 @@ module.exports = {
*/
create: async (ctx) => {
const data = await strapi.plugins['users-permissions'].services.user.add(ctx.request.body);
// Send 201 `created`

View File

@ -68,6 +68,12 @@ module.exports = {
}
},
getPolicies: async (ctx) => {
return ctx.send({
policies: _.without(_.keys(strapi.plugins['users-permissions'].config.policies), 'permissions')
});
},
getRole: async (ctx) => {
const { id } = ctx.params;
const role = await strapi.plugins['users-permissions'].services.userspermissions.getRole(id)[id];

View File

@ -5,81 +5,50 @@
*/
module.exports = {
// Before saving a value.
// Fired before an `insert` or `update` query.
// beforeSave: function (next) {
// // Use `this` to get your current object
// next();
// },
// beforeSave: async (model) => {},
// After saving a value.
// Fired after an `insert` or `update` query.
// afterSave: function (doc, next) {
// next();
// },
// afterSave: async (model, result) => {},
// Before fetching all values.
// Fired before a `fetchAll` operation.
// beforeFetchAll: function (next) {
// // Use `this` to get your current object
// next();
// },
// beforeFetchAll: async (model) => {},
// After fetching all values.
// Fired after a `fetchAll` operation.
// afterFetchAll: function (doc, next) {
// next();
// },
// afterFetchAll: async (model, results) => {},
// Fired before a `fetch` operation.
// beforeFetch: function (next) {
// // Use `this` to get your current object
// next();
// },
// beforeFetch: async (model) => {},
// After fetching a value.
// Fired after a `fetch` operation.
// afterFetch: function (doc, next) {
// next();
// },
// afterFetch: async (model, result) => {},
// Before creating a value.
// Fired before `insert` query.
// beforeCreate: function (next) {
// Use `this` to get your current object
// next();
// },
// beforeCreate: async (model) => {},
// After creating a value.
// Fired after `insert` query.
// afterCreate: function (doc, next) {
// next();
// },
// afterCreate: async (model, result) => {},
// Before updating a value.
// Fired before an `update` query.
// beforeUpdate: function (next) {
// // Use `this` to get your current object
// next();
// },
// beforeUpdate: async (model) => {},
// After updating a value.
// Fired after an `update` query.
// afterUpdate: function (doc, next) {
// next();
// },
// afterUpdate: async (model, result) => {},
// Before destroying a value.
// Fired before a `delete` query.
// beforeDestroy: function (next) {
// // Use `this` to get your current object
// next();
// },
// beforeDestroy: async (model) => {},
// After destroying a value.
// Fired after a `delete` query.
// afterDestroy: function (doc, next) {
// next();
// }
// afterDestroy: async (model, result) => {}
};

View File

@ -43,9 +43,7 @@ module.exports = {
values.password = await strapi.plugins['users-permissions'].services.user.hashPassword(values);
}
const data = await strapi.plugins['users-permissions'].models.user.create(_.omit(values, _.keys(_.groupBy(strapi.plugins['users-permissions'].models.user.associations, 'alias'))));
await strapi.hook.mongoose.manageRelations('user', _.merge(_.clone(data), { values }));
return data;
return strapi.query('user', 'users-permissions').create(values);
},
/**
@ -62,8 +60,7 @@ module.exports = {
values.password = await strapi.plugins['users-permissions'].services.user.hashPassword(values);
}
await strapi.hook.mongoose.manageRelations('user', _.merge(_.clone(params), { values }));
return strapi.plugins['users-permissions'].models.user.update(params, values, { multi: true });
return strapi.query('user', 'users-permissions').update(_.assign(params, values));
},
/**
@ -73,27 +70,12 @@ module.exports = {
*/
remove: async params => {
// Note: To get the full response of Mongo, use the `remove()` method
// or add spent the parameter `{ passRawResult: true }` as second argument.
const data = await strapi.plugins['users-permissions'].models.user.findOneAndRemove(params, {})
.populate(_.keys(_.groupBy(_.reject(strapi.plugins['users-permissions'].models.user.associations, {autoPopulate: false}), 'alias')).join(' '));
_.forEach(User.associations, async association => {
const search = (_.endsWith(association.nature, 'One')) ? { [association.via]: data._id } : { [association.via]: { $in: [data._id] } };
const update = (_.endsWith(association.nature, 'One')) ? { [association.via]: null } : { $pull: { [association.via]: data._id } };
await strapi.models[association.model || association.collection].update(
search,
update,
{ multi: true });
});
return data;
return strapi.query('user', 'users-permissions').delete(params);
},
hashPassword: function (user) {
hashPassword: function (user = {}) {
return new Promise((resolve) => {
if (!user.hasOwnProperty('password') || !user.password || this.isHashed(user.password)) {
if (!user.password || this.isHashed(user.password)) {
resolve(null);
} else {
bcrypt.hash(user.password, 10, (err, hash) => {

View File

@ -0,0 +1,56 @@
// Node.js core.
const REPL = require('repl');
const cluster = require('cluster');
const path = require('path');
// Public node modules.
const _ = require('lodash');
const { logger } = require('strapi-utils');
module.exports = function () {
try {
// Now load up the Strapi framework for real.
const strapi = function () {
try {
return require(path.resolve(process.cwd(), 'node_modules', 'strapi'));
} catch (e) {
return require('strapi');
}
}();
// Only log if the process is a master.
if (cluster.isMaster) {
strapi.log.info('Starting the application in interactive mode...');
}
strapi.start({}, function (err) {
// Log and exit the REPL in case there is an error
// while we were trying to start the server.
if (err) {
strapi.log.error('Could not load the Strapi framework.');
strapi.log.error('Are you using the latest stable version?');
process.exit(1);
}
// Open the Node.js REPL.
if ((cluster.isMaster && _.isEmpty(cluster.workers)) || cluster.worker.id === 1) {
const repl = REPL.start(strapi.config.info.name + ' > ' || 'strapi > ');
repl.on('exit', function (err) {
// Log and exit the REPL in case there is an error
// while we were trying to open the REPL.
if (err) {
strapi.log.error(err);
process.exit(1);
}
strapi.stop();
});
}
});
} catch (e) {
logger.error(e);
}
};

View File

@ -40,6 +40,13 @@ program
.description('output your version of Strapi')
.action(program.versionInformation);
// `$ strapi console`
program
.command('console')
.description('open the Strapi framework console')
.action(require('./strapi-console'));
// `$ strapi new`
program
.command('new')

View File

@ -84,7 +84,8 @@ module.exports = {
p.indexOf('hook') !== -1 ||
p.indexOf('middleware') !== -1 ||
p.indexOf('language') !== -1 ||
p.indexOf('queries') !== -1
p.indexOf('queries') !== -1 ||
p.indexOf('layout') !== -1
);
const optional = difference(files, aggregate);