Merge branch 'user-permissions' of https://github.com/strapi/strapi into user-permissions

This commit is contained in:
Jim Laurie 2017-12-04 16:51:32 +01:00
commit b54a2e087c
19 changed files with 107 additions and 63 deletions

View File

@ -1,6 +1,8 @@
# Don't check auto-generated stuff into git # Don't check auto-generated stuff into git
coverage coverage
node_modules node_modules
build
plugins.json
stats.json stats.json
package-lock.json package-lock.json

View File

@ -62,9 +62,9 @@ export class AdminPage extends React.Component { // eslint-disable-line react/pr
this.props.history.push(`/plugins/users-permissions/auth/${endPoint}`); this.props.history.push(`/plugins/users-permissions/auth/${endPoint}`);
} }
if (!this.isUrlProtected(props) && includes(props.location.pathname, 'login') && !this.hasAdminUser()) { // if (!this.isUrlProtected(props) && includes(props.location.pathname, 'login') && !this.hasAdminUser()) {
this.props.history.push('/plugins/users-permissions/auth/register'); // this.props.history.push('/plugins/users-permissions/auth/register');
} // }
if (!this.isUrlProtected(props) && includes(props.location.pathname, 'register') && this.hasAdminUser()) { if (!this.isUrlProtected(props) && includes(props.location.pathname, 'register') && this.hasAdminUser()) {
this.props.history.push('/plugins/users-permissions/auth/login'); this.props.history.push('/plugins/users-permissions/auth/login');

View File

@ -14,7 +14,7 @@ import cn from 'classnames';
import { get, isUndefined, map } from 'lodash'; import { get, isUndefined, map } from 'lodash';
// Design // Design
import Input from 'components/Input'; // import Input from 'components/Input';
import PluginCard from 'components/PluginCard'; import PluginCard from 'components/PluginCard';
import PluginHeader from 'components/PluginHeader'; import PluginHeader from 'components/PluginHeader';
@ -57,7 +57,7 @@ export class InstallPluginPage extends React.Component { // eslint-disable-line
description={{ id: 'app.components.InstallPluginPage.description' }} description={{ id: 'app.components.InstallPluginPage.description' }}
actions={[]} actions={[]}
/> />
<div className={cn('row', styles.inputContainer)}> {/*}<div className={cn('row', styles.inputContainer)}>
<Input <Input
customBootstrapClass="col-md-12" customBootstrapClass="col-md-12"
label="app.components.InstallPluginPage.InputSearch.label" label="app.components.InstallPluginPage.InputSearch.label"
@ -68,7 +68,7 @@ export class InstallPluginPage extends React.Component { // eslint-disable-line
validations={{}} validations={{}}
value={this.props.search} value={this.props.search}
/> />
</div> </div>*/}
<div className={cn('row', styles.wrapper)}> <div className={cn('row', styles.wrapper)}>
{map(this.props.availablePlugins, (plugin) => ( {map(this.props.availablePlugins, (plugin) => (
<PluginCard <PluginCard
@ -95,8 +95,8 @@ InstallPluginPage.propTypes = {
didFetchPlugins: PropTypes.bool.isRequired, didFetchPlugins: PropTypes.bool.isRequired,
getPlugins: PropTypes.func.isRequired, getPlugins: PropTypes.func.isRequired,
history: PropTypes.object.isRequired, history: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired, // onChange: PropTypes.func.isRequired,
search: PropTypes.string.isRequired, // search: PropTypes.string.isRequired,
}; };
const mapStateToProps = makeSelectInstallPluginPage(); const mapStateToProps = makeSelectInstallPluginPage();

View File

@ -11,7 +11,16 @@ import { connect } from 'react-redux';
import { bindActionCreators, compose } from 'redux'; import { bindActionCreators, compose } from 'redux';
import { createStructuredSelector } from 'reselect'; import { createStructuredSelector } from 'reselect';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { map, get, isObject, isEmpty, replace, toNumber, toString } from 'lodash'; import {
get,
includes,
isObject,
isEmpty,
map,
replace,
toNumber,
toString,
} from 'lodash';
import { router } from 'app'; import { router } from 'app';
// Components. // Components.
@ -121,7 +130,7 @@ export class Edit extends React.Component {
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (this.props.editSuccess !== nextProps.editSuccess) { if (this.props.editSuccess !== nextProps.editSuccess) {
if (!isEmpty(this.props.location.search)) { if (!isEmpty(this.props.location.search) && includes(this.props.location.search, '?redirectUrl')) {
router.push(replace(this.props.location.search, '?redirectUrl=', '')); router.push(replace(this.props.location.search, '?redirectUrl=', ''));
} else { } else {
router.push(replace(this.props.location.pathname, 'create', '')); router.push(replace(this.props.location.pathname, 'create', ''));
@ -169,7 +178,6 @@ export class Edit extends React.Component {
} }
const currentModel = get(this.props.models, ['models', this.props.currentModelName]) || get(this.props.models, ['plugins', this.source, 'models', this.props.currentModelName]); const currentModel = get(this.props.models, ['models', this.props.currentModelName]) || get(this.props.models, ['plugins', this.source, 'models', this.props.currentModelName]);
// Plugin header config // Plugin header config
const primaryKey = currentModel.primaryKey; const primaryKey = currentModel.primaryKey;
const mainField = get(currentModel, 'info.mainField') || primaryKey; const mainField = get(currentModel, 'info.mainField') || primaryKey;

View File

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

View File

@ -5,7 +5,8 @@
background-color: rgba(16, 22, 34, 0.02); background-color: rgba(16, 22, 34, 0.02);
border: 1px solid #E3E9F3; border: 1px solid #E3E9F3;
border-radius: 0.25rem; border-radius: 0.25rem;
border-bottom-left-radius: 0; border-bottom-left-radius: 0!important;
border-bottom-right-radius: 0!important;
color: rgba(16, 22, 34, 0.5); color: rgba(16, 22, 34, 0.5);
line-height: 3.2rem; line-height: 3.2rem;
font-size: 1.3rem; font-size: 1.3rem;
@ -14,6 +15,7 @@
text-transform: capitalize; text-transform: capitalize;
-moz-appearance: none; -moz-appearance: none;
-webkit-appearance: none; -webkit-appearance: none;
box-shadow: 0px 2px 1px rgba(104, 118, 142, 0.05);
&:before { &:before {
content: '\F002'; content: '\F002';
display: inline-table; display: inline-table;
@ -50,7 +52,7 @@
line-height: 3.4rem; line-height: 3.4rem;
font-size: 1.3rem; font-size: 1.3rem;
font-family: 'Lato' !important; font-family: 'Lato' !important;
box-shadow: 0px 1px 1px rgba(104, 118, 142, 0.05); box-shadow: 0px 2px 1px rgba(104, 118, 142, 0.05);
&:focus { &:focus {
border-color: #78caff; border-color: #78caff;
} }
@ -61,8 +63,8 @@
height: 16.3rem; height: 16.3rem;
overflow: scroll; overflow: scroll;
border: 1px solid #E3E9F3; border: 1px solid #E3E9F3;
border-top-left-radius: 0; border-top-left-radius: 0!important;
border-top-right-radius: 0; border-top-right-radius: 0!important;
border-top: none; border-top: none;
border-radius: 0.25rem; border-radius: 0.25rem;
> ul { > ul {

View File

@ -6,18 +6,26 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { router } from 'app';
import styles from './styles.scss'; import styles from './styles.scss';
function InputSearchLi({ onClick, isAdding, item }) { function InputSearchLi({ onClick, isAdding, item }) {
const icon = isAdding ? 'fa-plus' : 'fa-minus-circle'; const icon = isAdding ? 'fa-plus' : 'fa-minus-circle';
const liStyle = isAdding ? { cursor: 'pointer' } : {}; const liStyle = isAdding ? { cursor: 'pointer' } : {};
const handleClick = isAdding ? () => onClick(item) : () => {}; const handleClick = isAdding ? () => onClick(item) : () => {};
const path = `/plugins/content-manager/user/${item.id}?redirectUrl=/plugins/content-manager/user/?page=1&limit=20&sort=id&source=users-permissions`;
const handleGoto = (e) => {
e.preventDefault();
e.stopPropagation();
router.push(path);
};
return ( return (
<li className={styles.li} style={liStyle} onClick={handleClick}> <li className={styles.li} style={liStyle} onClick={handleClick}>
<div> <div>
<div> <div className={styles.container}>
{item.username} {item.username}
<i className="fa fa-external-link" onClick={handleGoto} />
</div> </div>
<div <div
onClick={(e) => { onClick={(e) => {

View File

@ -28,3 +28,13 @@
} }
} }
} }
.container {
>i {
margin-left: 10px;
color: #1C5DE7;
font-size: 10px;
cursor: pointer;
}
}

View File

@ -25,10 +25,13 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
} }
} }
// Roles that can't be deleted // Roles that can't be deleted && modified
// Don't delete this line // Don't delete this line
protectedRoleIDs = ['0']; protectedRoleIDs = ['0'];
// Roles that can't be deleted;
undeletableIDs = ['1'];
generateContent = () => { generateContent = () => {
let icons = [ let icons = [
{ {
@ -47,6 +50,10 @@ class ListRow extends React.Component { // eslint-disable-line react/prefer-stat
icons = []; icons = [];
} }
if (includes(this.undeletableIDs, get(this.props.item, 'id').toString())) {
icons = [{ icoType: 'pencil', onClick: this.handleClick }];
}
return ( return (
<div className={cn('row', styles.wrapper)}> <div className={cn('row', styles.wrapper)}>
<div className="col-md-2"> <div className="col-md-2">

View File

@ -7,7 +7,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Collapse } from 'reactstrap'; import { Collapse } from 'reactstrap';
import { capitalize, get, map } from 'lodash'; import { capitalize, get, isEmpty, map } from 'lodash';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import Controller from 'components/Controller'; import Controller from 'components/Controller';
@ -26,7 +26,10 @@ class Plugin extends React.Component { // eslint-disable-line react/prefer-state
handleClick = () => { handleClick = () => {
this.props.changePluginSelected(this.props.name); this.props.changePluginSelected(this.props.name);
this.setState({ collapse: !this.state.collapse });
if (!isEmpty(get(this.props.plugin, 'controllers'))) {
this.setState({ collapse: !this.state.collapse });
}
if (this.state.collapse) { if (this.state.collapse) {
this.context.resetShouldDisplayPoliciesHint(); this.context.resetShouldDisplayPoliciesHint();
@ -46,9 +49,9 @@ class Plugin extends React.Component { // eslint-disable-line react/prefer-state
<i className={`fa fa-${icon}`} /> <i className={`fa fa-${icon}`} />
</div> </div>
) : ''} ) : ''}
<span className={styles.name}>{this.props.name}</span> <div className={styles.name} style={{ width:'30%'}}>{this.props.name}</div>
&nbsp;&nbsp; &nbsp;&nbsp;
<span className={styles.description}> <div className={styles.description}>
{this.props.name === 'application' ? ( {this.props.name === 'application' ? (
<FormattedMessage <FormattedMessage
id="users-permissions.Plugin.permissions.application.description" id="users-permissions.Plugin.permissions.application.description"
@ -59,7 +62,7 @@ class Plugin extends React.Component { // eslint-disable-line react/prefer-state
values={{ name: capitalize(this.props.name) }} values={{ name: capitalize(this.props.name) }}
/> />
)} )}
</span> </div>
</div> </div>
<div className={this.state.collapse ? styles.chevronUp : styles.chevronDown}> <div className={this.state.collapse ? styles.chevronUp : styles.chevronDown}>
</div> </div>

View File

@ -46,9 +46,17 @@
> div:not(:first-child) { > div:not(:first-child) {
padding-top: 2.3rem; padding-top: 2.3rem;
} }
> div:last-child {
padding-bottom: 1.8rem;
}
} }
.description { .description {
// width: 50%;
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #8B91A0; color: #8B91A0;
font-size: 12px; font-size: 12px;
font-weight: 400; font-weight: 400;

View File

@ -29,7 +29,7 @@ class Policies extends React.Component { // eslint-disable-line react/prefer-sta
return ( return (
<div className={cn('col-md-5',styles.policies)}> <div className={cn('col-md-5',styles.policies)}>
<div className="container-fluid"> <div className="container-fluid">
<div className="row"> <div className={cn('row', styles.inputWrapper)}>
<div className={cn('col-md-12', styles.header)}> <div className={cn('col-md-12', styles.header)}>
<FormattedMessage id={`${baseTitle}.${title}`} /> <FormattedMessage id={`${baseTitle}.${title}`} />
</div> </div>

View File

@ -7,6 +7,14 @@
margin-bottom: 1.1rem; margin-bottom: 1.1rem;
padding-top: 2.8rem; padding-top: 2.8rem;
font-size: 18px; font-size: 18px;
font-weight: 900; font-weight: 800;
line-height: 3.6rem; line-height: 3.6rem;
} }
.inputWrapper {
> div:nth-child(2) {
> label {
font-weight: 800!important;
}
}
}

View File

@ -60,6 +60,9 @@ export class AuthPage extends React.Component { // eslint-disable-line react/pre
// NOTE: prepare for comfirm email; // NOTE: prepare for comfirm email;
// this.props.history.push(`/plugins/users-permissions/auth/register-success/${this.props.modifiedData.email}`); // this.props.history.push(`/plugins/users-permissions/auth/register-success/${this.props.modifiedData.email}`);
break; break;
case 'forgot-password':
console.log('fuck');
break;
default: default:
} }
@ -134,6 +137,9 @@ export class AuthPage extends React.Component { // eslint-disable-line react/pre
render() { render() {
const inputs = get(form, ['form', this.props.match.params.authType]); const inputs = get(form, ['form', this.props.match.params.authType]);
const divStyle = this.props.match.params.authType === 'register' ? { marginTop: '3.2rem' } : { marginTop: '.9rem' }; const divStyle = this.props.match.params.authType === 'register' ? { marginTop: '3.2rem' } : { marginTop: '.9rem' };
const withLogo = this.props.match.params.authType === 'register' ? (
<div className={styles.logoContainer}><img src={LogoStrapi} alt="logo" /></div>
) : '';
const headerDescription = this.props.match.params.authType === 'register' ? const headerDescription = this.props.match.params.authType === 'register' ?
<FormattedMessage id="users-permissions.Auth.header.register.description" /> <FormattedMessage id="users-permissions.Auth.header.register.description" />
: <span />; : <span />;
@ -181,6 +187,7 @@ export class AuthPage extends React.Component { // eslint-disable-line react/pre
{this.renderLink()} {this.renderLink()}
</div> </div>
</div> </div>
{withLogo}
</div> </div>
); );
} }

View File

@ -77,3 +77,13 @@
} }
} }
} }
.logoContainer {
position: absolute;
bottom: 20px;
left: 10px;
> img {
height: 20px;
}
}

View File

@ -17,12 +17,12 @@
"Auth.form.login.password.label": "Password", "Auth.form.login.password.label": "Password",
"Auth.form.login.rememberMe.label": "Remember me", "Auth.form.login.rememberMe.label": "Remember me",
"Auth.form.login.username.label": "Username", "Auth.form.login.username.label": "Username",
"Auth.form.login.username.placeholder": "Soupette", "Auth.form.login.username.placeholder": "John Doe",
"Auth.form.register.email.label": "Email", "Auth.form.register.email.label": "Email",
"Auth.form.register.email.placeholder": "johndoe@gmail.com", "Auth.form.register.email.placeholder": "johndoe@gmail.com",
"Auth.form.register.username.label": "Username", "Auth.form.register.username.label": "Username",
"Auth.form.register.username.placeholder": "Soupette", "Auth.form.register.username.placeholder": "John Doe",
"Auth.form.register.password.label": "Password", "Auth.form.register.password.label": "Password",
"Auth.form.register.confirmPassword.label": "Confirmation Password", "Auth.form.register.confirmPassword.label": "Confirmation Password",
@ -114,7 +114,7 @@
"Policies.InputSelect.empty": "None", "Policies.InputSelect.empty": "None",
"Policies.InputSelect.label": "Allow to perform this action for:", "Policies.InputSelect.label": "Allow to perform this action for:",
"Policies.header.hint": "Select the application's actions or the plugin's actions and put your mouse over to display the bounded route", "Policies.header.hint": "Select the application's actions or the plugin's actions and click on the cog icon to display the bounded route",
"Policies.header.title": "Advanced settings", "Policies.header.title": "Advanced settings",
"PopUpForm.button.cancel": "Cancel", "PopUpForm.button.cancel": "Cancel",

View File

@ -17,12 +17,12 @@
"Auth.form.login.password.label": "Mot de Passe", "Auth.form.login.password.label": "Mot de Passe",
"Auth.form.login.rememberMe.label": "Se souvenir de moi", "Auth.form.login.rememberMe.label": "Se souvenir de moi",
"Auth.form.login.username.label": "Username", "Auth.form.login.username.label": "Username",
"Auth.form.login.username.placeholder": "Soupette", "Auth.form.login.username.placeholder": "John Doe",
"Auth.form.register.email.label": "Email", "Auth.form.register.email.label": "Email",
"Auth.form.register.email.placeholder": "johndoe@gmail.com", "Auth.form.register.email.placeholder": "johndoe@gmail.com",
"Auth.form.register.username.label": "Username", "Auth.form.register.username.label": "Username",
"Auth.form.register.username.placeholder": "Soupette", "Auth.form.register.username.placeholder": "John Doe",
"Auth.form.register.password.label": "Mot de Passe", "Auth.form.register.password.label": "Mot de Passe",
"Auth.form.register.confirmPassword.label": "Confirmez le Mot de Passe", "Auth.form.register.confirmPassword.label": "Confirmez le Mot de Passe",
@ -115,8 +115,8 @@
"Policies.InputSelect.empty": "Aucune", "Policies.InputSelect.empty": "Aucune",
"Policies.InputSelect.label": "Autorisez cette action pour :", "Policies.InputSelect.label": "Autorisez cette action pour :",
"Policies.header.hint": "Sélectionnez ...", "Policies.header.hint": "Sélectionnez les actions de l'application ou d'un plugin et cliquer sur l'icon de paramètres pour voir les routes associées à cette action",
"Policies.header.tile": "Paramètres avancés", "Policies.header.title": "Paramètres avancés",
"popUpForm.button.cancel": "Annuler", "popUpForm.button.cancel": "Annuler",
"popUpForm.button.save": "Sauvegarder", "popUpForm.button.save": "Sauvegarder",

View File

@ -256,34 +256,7 @@
} }
}, },
"application": { "application": {
"controllers": { "controllers": {}
"product": {
"find": {
"enabled": true,
"policy": ""
},
"findOne": {
"enabled": true,
"policy": ""
},
"create": {
"enabled": true,
"policy": ""
},
"update": {
"enabled": true,
"policy": ""
},
"destroy": {
"enabled": true,
"policy": ""
},
"identity": {
"enabled": true,
"policy": ""
}
}
}
} }
} }
} }

View File

@ -47,7 +47,7 @@ module.exports = {
return ctx.badRequest(null, [{ messages: [{ id: 'Bad request' }] }]); return ctx.badRequest(null, [{ messages: [{ id: 'Bad request' }] }]);
} }
if (role === '0') { if (role === '0' || role === '1') {
return ctx.badRequest(null, [{ messages: [{ id: 'Unauthorized' }] }]); return ctx.badRequest(null, [{ messages: [{ id: 'Unauthorized' }] }]);
} }