merges master
This commit is contained in:
@@ -96,6 +96,10 @@ async function login(args) {
|
||||
cookieOptions.secure = true;
|
||||
}
|
||||
|
||||
if (collectionConfig.auth.sameSite) {
|
||||
cookieOptions.sameSite = collectionConfig.auth.sameSite;
|
||||
}
|
||||
|
||||
if (args.req.headers && args.req.headers.origin && args.req.headers.origin.indexOf('localhost') === -1) {
|
||||
let domain = args.req.headers.origin.replace('https://', '');
|
||||
domain = domain.replace('http://', '');
|
||||
|
||||
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import DefaultNav from '../../elements/Nav';
|
||||
import { StepNavProvider } from '../../elements/StepNav';
|
||||
import customComponents from '../../customComponents';
|
||||
import Meta from '../../utilities/Meta';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
@@ -19,6 +20,11 @@ const Default = ({ children, className }) => {
|
||||
return (
|
||||
<div className={classes}>
|
||||
<StepNavProvider>
|
||||
<Meta
|
||||
title="Dashboard"
|
||||
description="Dashboard for Payload CMS"
|
||||
keywords="Dashboard, Payload, CMS"
|
||||
/>
|
||||
<Nav />
|
||||
<div className={`${baseClass}__wrap`}>
|
||||
{children}
|
||||
|
||||
73
src/client/components/utilities/Meta/index.js
Normal file
73
src/client/components/utilities/Meta/index.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Helmet from 'react-helmet';
|
||||
import config from 'payload/config';
|
||||
|
||||
function Meta({ description, lang, meta, title, image, keywords }) {
|
||||
const titleSuffix = config?.admin?.meta?.titleSuffix ?? '- Payload';
|
||||
return (
|
||||
<Helmet
|
||||
htmlAttributes={{
|
||||
lang,
|
||||
}}
|
||||
title={`${title} ${titleSuffix}`}
|
||||
meta={[
|
||||
{
|
||||
name: 'description',
|
||||
content: description,
|
||||
},
|
||||
{
|
||||
name: 'keywords',
|
||||
content: keywords,
|
||||
},
|
||||
{
|
||||
property: 'og:title',
|
||||
content: `${title} ${titleSuffix}`,
|
||||
},
|
||||
{
|
||||
property: 'og:image',
|
||||
content: image,
|
||||
},
|
||||
{
|
||||
property: 'og:description',
|
||||
content: description,
|
||||
},
|
||||
{
|
||||
property: 'og:type',
|
||||
content: 'website',
|
||||
},
|
||||
{
|
||||
name: 'twitter:card',
|
||||
content: 'summary',
|
||||
},
|
||||
{
|
||||
name: 'twitter:title',
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
name: 'twitter:description',
|
||||
content: description,
|
||||
},
|
||||
].concat(meta)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Meta.defaultProps = {
|
||||
lang: 'en',
|
||||
meta: [],
|
||||
description: '',
|
||||
image: '/images/default-og.png',
|
||||
keywords: 'CMS, Admin, Dashboard',
|
||||
};
|
||||
|
||||
Meta.propTypes = {
|
||||
description: PropTypes.string,
|
||||
lang: PropTypes.string,
|
||||
meta: PropTypes.arrayOf(PropTypes.object),
|
||||
title: PropTypes.string.isRequired,
|
||||
image: PropTypes.string,
|
||||
keywords: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Meta;
|
||||
@@ -12,6 +12,7 @@ import CopyToClipboard from '../../elements/CopyToClipboard';
|
||||
import * as fieldTypes from '../../forms/field-types';
|
||||
import RenderTitle from '../../elements/RenderTitle';
|
||||
import LeaveWithoutSaving from '../../modals/LeaveWithoutSaving';
|
||||
import Meta from '../../utilities/Meta';
|
||||
import Auth from '../collections/Edit/Auth';
|
||||
import Loading from '../../elements/Loading';
|
||||
|
||||
@@ -57,6 +58,11 @@ const DefaultAccount = (props) => {
|
||||
disabled={!hasSavePermission}
|
||||
>
|
||||
<div className={`${baseClass}__main`}>
|
||||
<Meta
|
||||
title="Account"
|
||||
description="Account of current user"
|
||||
keywords="Account, Dashboard, Payload, CMS"
|
||||
/>
|
||||
<Eyebrow />
|
||||
<LeaveWithoutSaving />
|
||||
<div className={`${baseClass}__edit`}>
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import config from 'payload/config';
|
||||
import MinimalTemplate from '../../templates/Minimal';
|
||||
import Meta from '../../utilities/Meta';
|
||||
import Form from '../../forms/Form';
|
||||
import RenderFields from '../../forms/RenderFields';
|
||||
import * as fieldTypes from '../../forms/field-types';
|
||||
@@ -48,6 +49,11 @@ const CreateFirstUser = (props) => {
|
||||
<MinimalTemplate className={baseClass}>
|
||||
<h1>Welcome</h1>
|
||||
<p>To begin, create your first user.</p>
|
||||
<Meta
|
||||
title="Create First User"
|
||||
description="Create first user"
|
||||
keywords="Create, Payload, CMS"
|
||||
/>
|
||||
<Form
|
||||
onSuccess={onSuccess}
|
||||
method="POST"
|
||||
|
||||
@@ -7,6 +7,7 @@ import Form from '../../forms/Form';
|
||||
import Email from '../../forms/field-types/Email';
|
||||
import FormSubmit from '../../forms/Submit';
|
||||
import Button from '../../elements/Button';
|
||||
import Meta from '../../utilities/Meta';
|
||||
import { useUser } from '../../data/User';
|
||||
|
||||
import './index.scss';
|
||||
@@ -42,6 +43,12 @@ const ForgotPassword = () => {
|
||||
if (user) {
|
||||
return (
|
||||
<MinimalTemplate className={baseClass}>
|
||||
<Meta
|
||||
title="Forgot Password"
|
||||
description="Forgot password"
|
||||
keywords="Forgot, Password, Payload, CMS"
|
||||
/>
|
||||
|
||||
<h1>You're already logged in</h1>
|
||||
<p>
|
||||
To change your password, go to your
|
||||
|
||||
@@ -7,6 +7,7 @@ import PreviewButton from '../../elements/PreviewButton';
|
||||
import FormSubmit from '../../forms/Submit';
|
||||
import RenderFields from '../../forms/RenderFields';
|
||||
import CopyToClipboard from '../../elements/CopyToClipboard';
|
||||
import Meta from '../../utilities/Meta';
|
||||
import * as fieldTypes from '../../forms/field-types';
|
||||
import LeaveWithoutSaving from '../../modals/LeaveWithoutSaving';
|
||||
|
||||
@@ -39,6 +40,11 @@ const DefaultGlobalView = (props) => {
|
||||
initialState={initialState}
|
||||
>
|
||||
<div className={`${baseClass}__main`}>
|
||||
<Meta
|
||||
title={label}
|
||||
description={label}
|
||||
keywords={`${label}, Payload, CMS`}
|
||||
/>
|
||||
<Eyebrow />
|
||||
<LeaveWithoutSaving />
|
||||
<div className={`${baseClass}__edit`}>
|
||||
|
||||
@@ -8,6 +8,7 @@ import Email from '../../forms/field-types/Email';
|
||||
import Password from '../../forms/field-types/Password';
|
||||
import FormSubmit from '../../forms/Submit';
|
||||
import Button from '../../elements/Button';
|
||||
import Meta from '../../utilities/Meta';
|
||||
import { useUser } from '../../data/User';
|
||||
|
||||
import './index.scss';
|
||||
@@ -30,6 +31,11 @@ const Login = () => {
|
||||
if (user) {
|
||||
return (
|
||||
<MinimalTemplate className={baseClass}>
|
||||
<Meta
|
||||
title="Login"
|
||||
description="Login user"
|
||||
keywords="Login, Payload, CMS"
|
||||
/>
|
||||
<div className={`${baseClass}__wrap`}>
|
||||
<h1>Already logged in</h1>
|
||||
<p>
|
||||
@@ -54,6 +60,11 @@ const Login = () => {
|
||||
|
||||
return (
|
||||
<MinimalTemplate className={baseClass}>
|
||||
<Meta
|
||||
title="Login"
|
||||
description="Login user"
|
||||
keywords="Login, Payload, CMS"
|
||||
/>
|
||||
<div className={`${baseClass}__brand`}>
|
||||
<Logo />
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@ import config from 'payload/config';
|
||||
import { useUser } from '../../data/User';
|
||||
import Minimal from '../../templates/Minimal';
|
||||
import Button from '../../elements/Button';
|
||||
import Meta from '../../utilities/Meta';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
@@ -22,6 +23,11 @@ const Logout = (props) => {
|
||||
|
||||
return (
|
||||
<Minimal className={baseClass}>
|
||||
<Meta
|
||||
title="Logout"
|
||||
description="Logout user"
|
||||
keywords="Logout, Payload, CMS"
|
||||
/>
|
||||
<div className={`${baseClass}__wrap`}>
|
||||
{inactivity && (
|
||||
<h2>You have been logged out due to inactivity.</h2>
|
||||
|
||||
@@ -3,6 +3,7 @@ import config from 'payload/config';
|
||||
import Eyebrow from '../../elements/Eyebrow';
|
||||
import { useStepNav } from '../../elements/StepNav';
|
||||
import Button from '../../elements/Button';
|
||||
import Meta from '../../utilities/Meta';
|
||||
|
||||
const { routes: { admin } } = config;
|
||||
|
||||
@@ -17,6 +18,11 @@ const NotFound = () => {
|
||||
|
||||
return (
|
||||
<div className="not-found">
|
||||
<Meta
|
||||
title="Not Found"
|
||||
description="Page not found"
|
||||
keywords="404, Not found, Payload, CMS"
|
||||
/>
|
||||
<Eyebrow />
|
||||
<h1>Nothing found</h1>
|
||||
<p>Sorry—there is nothing to correspond with your request.</p>
|
||||
|
||||
@@ -7,6 +7,7 @@ import Password from '../../forms/field-types/Password';
|
||||
import ConfirmPassword from '../../forms/field-types/ConfirmPassword';
|
||||
import FormSubmit from '../../forms/Submit';
|
||||
import Button from '../../elements/Button';
|
||||
import Meta from '../../utilities/Meta';
|
||||
import { useUser } from '../../data/User';
|
||||
|
||||
import './index.scss';
|
||||
@@ -31,6 +32,12 @@ const ResetPassword = () => {
|
||||
if (user) {
|
||||
return (
|
||||
<MinimalTemplate className={baseClass}>
|
||||
<Meta
|
||||
title="Reset Password"
|
||||
description="Reset password"
|
||||
keywords="Reset Password, Payload, CMS"
|
||||
/>
|
||||
|
||||
<div className={`${baseClass}__wrap`}>
|
||||
<h1>Already logged in</h1>
|
||||
<p>
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
import React from 'react';
|
||||
import config from 'payload/config';
|
||||
import Button from '../../elements/Button';
|
||||
import Meta from '../../utilities/Meta';
|
||||
import MinimalTemplate from '../../templates/Minimal';
|
||||
|
||||
const { routes: { admin } } = config;
|
||||
|
||||
const Unauthorized = () => {
|
||||
return (
|
||||
<MinimalTemplate className="unauthorized">
|
||||
<h1>Not authorized</h1>
|
||||
<p>You are not allowed to access this page.</p>
|
||||
<br />
|
||||
<Button
|
||||
el="link"
|
||||
to={`${admin}/logout`}
|
||||
>
|
||||
Log out
|
||||
</Button>
|
||||
</MinimalTemplate>
|
||||
);
|
||||
};
|
||||
|
||||
const Unauthorized = () => (
|
||||
<MinimalTemplate className="unauthorized">
|
||||
<Meta
|
||||
title="Unauthorized"
|
||||
description="Unauthorized"
|
||||
keywords="Unauthorized, Payload, CMS"
|
||||
/>
|
||||
<p>You are not allowed to access this page.</p>
|
||||
<br />
|
||||
<Button
|
||||
el="link"
|
||||
to={`${admin}/logout`}
|
||||
>
|
||||
Log out
|
||||
</Button>
|
||||
</MinimalTemplate>
|
||||
);
|
||||
export default Unauthorized;
|
||||
|
||||
@@ -12,6 +12,7 @@ import RenderFields from '../../../forms/RenderFields';
|
||||
import CopyToClipboard from '../../../elements/CopyToClipboard';
|
||||
import DuplicateDocument from '../../../elements/DuplicateDocument';
|
||||
import DeleteDocument from '../../../elements/DeleteDocument';
|
||||
import Meta from '../../../utilities/Meta';
|
||||
import * as fieldTypes from '../../../forms/field-types';
|
||||
import RenderTitle from '../../../elements/RenderTitle';
|
||||
import LeaveWithoutSaving from '../../../modals/LeaveWithoutSaving';
|
||||
@@ -69,6 +70,11 @@ const DefaultEditView = (props) => {
|
||||
initialState={initialState}
|
||||
>
|
||||
<div className={`${baseClass}__main`}>
|
||||
<Meta
|
||||
title={`${isEditing ? 'Editing' : 'Creating'} - ${collection.labels.singular}`}
|
||||
description={`${isEditing ? 'Editing' : 'Creating'} - ${collection.labels.singular}`}
|
||||
keywords={`${collection.labels.singular}, Payload, CMS`}
|
||||
/>
|
||||
<Eyebrow />
|
||||
<LeaveWithoutSaving />
|
||||
<div className={`${baseClass}__edit`}>
|
||||
|
||||
@@ -10,6 +10,7 @@ import Pill from '../../../elements/Pill';
|
||||
import Button from '../../../elements/Button';
|
||||
import SortColumn from '../../../elements/SortColumn';
|
||||
import Table from '../../../elements/Table';
|
||||
import Meta from '../../../utilities/Meta';
|
||||
import Cell from './Cell';
|
||||
|
||||
import './index.scss';
|
||||
@@ -42,6 +43,9 @@ const DefaultList = (props) => {
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<Meta
|
||||
title={collection.labels.plural}
|
||||
/>
|
||||
<Eyebrow />
|
||||
<div className={`${baseClass}__wrap`}>
|
||||
<header className={`${baseClass}__header`}>
|
||||
|
||||
@@ -2,7 +2,7 @@ const mongoose = require('mongoose');
|
||||
const express = require('express');
|
||||
const mongooseHidden = require('mongoose-hidden')({
|
||||
hidden: {
|
||||
salt: true, hash: true, _id: true, __v: true,
|
||||
_id: true, __v: true,
|
||||
},
|
||||
applyRecursively: true,
|
||||
});
|
||||
@@ -21,6 +21,8 @@ function registerCollections() {
|
||||
|
||||
if (collection.auth) {
|
||||
schema.plugin(passportLocalMongoose, { usernameField: 'email' });
|
||||
schema.path('hash').options.hide = true;
|
||||
schema.path('salt').options.hide = true;
|
||||
}
|
||||
|
||||
schema.plugin(mongooseHidden);
|
||||
|
||||
@@ -128,7 +128,7 @@ module.exports = (config) => {
|
||||
|
||||
const plugins = [
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve(__dirname, '../client/index.html'),
|
||||
template: config.admin && config.admin.indexHTML ? config.admin.indexHTML : path.resolve(__dirname, '../client/index.html'),
|
||||
filename: './index.html',
|
||||
}),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
|
||||
@@ -119,7 +119,7 @@ module.exports = (config) => {
|
||||
const plugins = [
|
||||
// new BundleAnalyzerPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve(__dirname, '../client/index.html'),
|
||||
template: config.admin && config.admin.indexHTML ? config.admin.indexHTML : path.resolve(__dirname, '../client/index.html'),
|
||||
filename: './index.html',
|
||||
minify: true,
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user