namespaces API keys, finds collection based on JWT collection payload

This commit is contained in:
James
2020-07-01 18:32:39 -04:00
parent b1b6add2c0
commit fef816fac3
19 changed files with 132 additions and 97 deletions

View File

@@ -26,7 +26,7 @@ const {
const Routes = () => {
const [initialized, setInitialized] = useState(null);
const { user, permissions: { canAccessAdmin } } = useUser();
const { user, permissions, permissions: { canAccessAdmin } } = useUser();
useEffect(() => {
requests.get(`${routes.api}/${userSlug}/init`).then(res => res.json().then((data) => {
@@ -88,77 +88,93 @@ const Routes = () => {
</Route>
{collections.map((collection) => {
return (
<Route
key={`${collection.slug}-list`}
path={`${match.url}/collections/${collection.slug}`}
exact
render={(routeProps) => {
return (
<List
{...routeProps}
collection={collection}
/>
);
}}
/>
);
if (permissions?.[collection.slug]?.read?.permission) {
return (
<Route
key={`${collection.slug}-list`}
path={`${match.url}/collections/${collection.slug}`}
exact
render={(routeProps) => {
return (
<List
{...routeProps}
collection={collection}
/>
);
}}
/>
);
}
return null;
})}
{collections.map((collection) => {
return (
<Route
key={`${collection.slug}-create`}
path={`${match.url}/collections/${collection.slug}/create`}
exact
render={(routeProps) => {
return (
<Edit
{...routeProps}
collection={collection}
/>
);
}}
/>
);
if (permissions?.[collection.slug]?.create?.permission) {
return (
<Route
key={`${collection.slug}-create`}
path={`${match.url}/collections/${collection.slug}/create`}
exact
render={(routeProps) => {
return (
<Edit
{...routeProps}
collection={collection}
/>
);
}}
/>
);
}
return null;
})}
{collections.map((collection) => {
return (
<Route
key={`${collection.slug}-edit`}
path={`${match.url}/collections/${collection.slug}/:id`}
exact
render={(routeProps) => {
return (
<Edit
isEditing
{...routeProps}
collection={collection}
/>
);
}}
/>
);
if (permissions?.[collection.slug]?.read?.permission) {
return (
<Route
key={`${collection.slug}-edit`}
path={`${match.url}/collections/${collection.slug}/:id`}
exact
render={(routeProps) => {
return (
<Edit
isEditing
{...routeProps}
collection={collection}
/>
);
}}
/>
);
}
return null;
})}
{globals && globals.map((global) => {
return (
<Route
key={`${global.slug}`}
path={`${match.url}/globals/${global.slug}`}
exact
render={(routeProps) => {
return (
<EditGlobal
{...routeProps}
global={global}
/>
);
}}
/>
);
if (permissions?.[global.slug]?.read?.permission) {
return (
<Route
key={`${global.slug}`}
path={`${match.url}/globals/${global.slug}`}
exact
render={(routeProps) => {
return (
<EditGlobal
{...routeProps}
global={global}
/>
);
}}
/>
);
}
return null;
})}
<Route path={`${match.url}*`}>
<NotFound />
</Route>

View File

@@ -1,6 +1,8 @@
@import '../../../scss/styles.scss';
.file-details {
background-color: $color-background-gray;
header {
display: flex;
align-items: flex-start;

View File

@@ -6,7 +6,7 @@ import Label from '../../Label';
import Button from '../../../elements/Button';
import CopyToClipboard from '../../../elements/CopyToClipboard';
import { text } from '../../../../../fields/validations';
import useForm from '../../Form/useForm';
import useFormFields from '../../Form/useFormFields';
import './index.scss';
@@ -19,7 +19,7 @@ const APIKey = (props) => {
initialData,
} = props;
const { getField } = useForm();
const { getField } = useFormFields();
const apiKey = getField(path);
@@ -36,7 +36,7 @@ const APIKey = (props) => {
const fieldType = useFieldType({
path: 'apiKey',
initialData: initialData || generateAPIKey(),
initialData: initialData || uuidv4(),
validate,
});

View File

@@ -5,7 +5,7 @@ import Password from '../Password';
import Checkbox from '../Checkbox';
import Button from '../../../elements/Button';
import ConfirmPassword from '../ConfirmPassword';
import useForm from '../../Form/useForm';
import useFormFields from '../../Form/useFormFields';
import APIKey from './APIKey';
import './index.scss';
@@ -15,7 +15,7 @@ const baseClass = 'auth-fields';
const Auth = (props) => {
const { initialData, useAPIKey, requirePassword } = props;
const [changingPassword, setChangingPassword] = useState(requirePassword);
const { getField } = useForm();
const { getField } = useFormFields();
const enableAPIKey = getField('enableAPIKey');
@@ -76,12 +76,14 @@ const Auth = (props) => {
Auth.defaultProps = {
initialData: undefined,
useAPIKey: false,
requirePassword: false,
};
Auth.propTypes = {
fieldTypes: PropTypes.shape({}).isRequired,
initialData: PropTypes.shape({}),
useAPIKey: PropTypes.bool,
requirePassword: PropTypes.bool,
};
export default Auth;

View File

@@ -2,12 +2,12 @@ import React, { useCallback } from 'react';
import useFieldType from '../../useFieldType';
import Label from '../../Label';
import Error from '../../Error';
import useForm from '../../Form/useForm';
import useFormFields from '../../Form/useFormFields';
import './index.scss';
const ConfirmPassword = () => {
const { getField } = useForm();
const { getField } = useFormFields();
const password = getField('password');
const validate = useCallback((value) => {

View File

@@ -23,6 +23,7 @@ const Textarea = (props) => {
readOnly,
minLength,
maxLength,
rows,
} = props;
const path = pathFromProps || name;
@@ -77,6 +78,7 @@ const Textarea = (props) => {
placeholder={placeholder}
id={path}
name={path}
rows={rows}
/>
</div>
);
@@ -95,6 +97,7 @@ Textarea.defaultProps = {
readOnly: false,
minLength: undefined,
maxLength: undefined,
rows: 8,
};
Textarea.propTypes = {
@@ -111,6 +114,7 @@ Textarea.propTypes = {
readOnly: PropTypes.bool,
minLength: PropTypes.number,
maxLength: PropTypes.number,
rows: PropTypes.number,
};
export default withCondition(Textarea);

View File

@@ -5,6 +5,7 @@
textarea {
@include formInput();
height: auto;
min-height: base(3);
}

View File

@@ -20,7 +20,7 @@ const Logout = () => {
return (
<Minimal className={baseClass}>
<div className={`${baseClass}__wrap`}>
<h1>You have been logged out.</h1>
<h2>You have been logged out successfully.</h2>
<br />
<Button
el="anchor"

View File

@@ -25,7 +25,7 @@ const DefaultEditView = (props) => {
const { params: { id } = {} } = useRouteMatch();
const {
collection, isEditing, data, onSave,
collection, isEditing, data, onSave, permissions,
} = props;
const {
@@ -176,6 +176,20 @@ DefaultEditView.propTypes = {
createdAt: PropTypes.string,
}),
onSave: PropTypes.func,
permissions: PropTypes.shape({
create: PropTypes.shape({
permission: PropTypes.bool,
}),
read: PropTypes.shape({
permission: PropTypes.bool,
}),
update: PropTypes.shape({
permission: PropTypes.bool,
}),
delete: PropTypes.shape({
permission: PropTypes.bool,
}),
}).isRequired,
};
export default DefaultEditView;

View File

@@ -4,6 +4,7 @@ import { useRouteMatch, useHistory, useLocation } from 'react-router-dom';
import config from 'payload/config';
import { useStepNav } from '../../../elements/StepNav';
import usePayloadAPI from '../../../../hooks/usePayloadAPI';
import { useUser } from '../../../data/User';
import formatFields from './formatFields';
import RenderCustomComponent from '../../../utilities/RenderCustomComponent';
@@ -17,6 +18,7 @@ const EditView = (props) => {
const history = useHistory();
const { setStepNav } = useStepNav();
const [fields, setFields] = useState([]);
const { permissions } = useUser();
const { collection, isEditing } = props;
@@ -75,6 +77,7 @@ const EditView = (props) => {
componentProps={{
data: dataToRender,
collection: { ...collection, fields },
permissions: permissions?.[collection.slug],
isEditing,
onSave,
}}

View File

@@ -1,7 +1,7 @@
import useForm from '../components/forms/Form/useForm';
import useFormFields from '../components/forms/Form/useFormFields';
const useTitle = (useAsTitle) => {
const { getField } = useForm();
const { getField } = useFormFields();
const titleField = getField(useAsTitle);
return titleField?.value;
};

View File

@@ -33,7 +33,7 @@
%h2 {
margin: 0 0 base(1);
font-size: base(1.25);
line-height: base(1.25);
line-height: base(1.5);
letter-spacing: -.5px;
@include small-break {