feat: initial drafts and versions merge

This commit is contained in:
James
2022-02-06 12:13:52 -05:00
199 changed files with 6182 additions and 834 deletions

View File

@@ -12,7 +12,7 @@ type Arguments = {
operation: Operation
overrideAccess: boolean
req: PayloadRequest
id: string
id: string | number
relationshipPopulations: (() => Promise<void>)[]
depth: number
currentDepth: number

View File

@@ -1,60 +0,0 @@
import crypto from 'crypto';
import { Field, FieldHook } from '../config/types';
const encryptKey: FieldHook = ({ req, value }) => (value ? req.payload.encrypt(value as string) : undefined);
const decryptKey: FieldHook = ({ req, value }) => (value ? req.payload.decrypt(value as string) : undefined);
export default [
{
name: 'enableAPIKey',
label: 'Enable API Key',
type: 'checkbox',
defaultValue: false,
admin: {
components: {
Field: () => null,
},
},
},
{
name: 'apiKey',
label: 'API Key',
type: 'text',
admin: {
components: {
Field: () => null,
},
},
hooks: {
beforeChange: [
encryptKey,
],
afterRead: [
decryptKey,
],
},
},
{
name: 'apiKeyIndex',
type: 'text',
hidden: true,
admin: {
disabled: true,
},
hooks: {
beforeValidate: [
async ({ data, req, value }) => {
if (data.apiKey) {
return crypto.createHmac('sha1', req.payload.secret)
.update(data.apiKey as string)
.digest('hex');
}
if (data.enableAPIKey === false) {
return null;
}
return value;
},
],
},
},
] as Field[];

View File

@@ -1,15 +0,0 @@
import { Field } from '../config/types';
export default [
{
name: 'loginAttempts',
type: 'number',
hidden: true,
defaultValue: 0,
},
{
name: 'lockUntil',
type: 'date',
hidden: true,
},
] as Field[];

View File

@@ -1,27 +0,0 @@
import { email } from '../validations';
import { Field } from '../config/types';
export default [
{
name: 'email',
label: 'Email',
type: 'email',
validate: email,
unique: true,
admin: {
components: {
Field: () => null,
},
},
},
{
name: 'resetPasswordToken',
type: 'text',
hidden: true,
},
{
name: 'resetPasswordExpiration',
type: 'date',
hidden: true,
},
] as Field[];

View File

@@ -1,43 +0,0 @@
import { Field, FieldHook } from '../config/types';
const autoRemoveVerificationToken: FieldHook = ({ originalDoc, data, value, operation }) => {
// If a user manually sets `_verified` to true,
// and it was `false`, set _verificationToken to `null`.
// This is useful because the admin panel
// allows users to set `_verified` to true manually
if (operation === 'update') {
if (data?._verified === true && originalDoc?._verified === false) {
return null;
}
}
return value;
};
export default [
{
name: '_verified',
type: 'checkbox',
access: {
create: () => false,
update: ({ req: { user } }) => Boolean(user),
read: ({ req: { user } }) => Boolean(user),
},
admin: {
components: {
Field: () => null,
},
},
},
{
name: '_verificationToken',
type: 'text',
hidden: true,
hooks: {
beforeChange: [
autoRemoveVerificationToken,
],
},
},
] as Field[];

View File

@@ -1,149 +0,0 @@
import { Field } from '../config/types';
import { Config } from '../../config/types';
import { CollectionConfig } from '../../collections/config/types';
import { mimeTypeValidator } from '../../uploads/mimeTypeValidator';
import { IncomingUploadType } from '../../uploads/types';
type Options = {
config: Config
collection: CollectionConfig
}
const getBaseUploadFields = ({ config, collection }: Options): Field[] => {
const uploadOptions: IncomingUploadType = typeof collection.upload === 'object' ? collection.upload : {};
const mimeType: Field = {
name: 'mimeType',
label: 'MIME Type',
type: 'text',
admin: {
readOnly: true,
disabled: true,
},
};
const url: Field = {
name: 'url',
label: 'URL',
type: 'text',
admin: {
readOnly: true,
disabled: true,
},
};
const width: Field = {
name: 'width',
label: 'Width',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
};
const height: Field = {
name: 'height',
label: 'Height',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
};
const filesize: Field = {
name: 'filesize',
label: 'File Size',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
};
const filename: Field = {
name: 'filename',
label: 'File Name',
type: 'text',
index: true,
unique: true,
admin: {
readOnly: true,
disabled: true,
},
};
let uploadFields: Field[] = [
{
...url,
hooks: {
afterRead: [
({ data }) => {
if (data?.filename) {
return `${config.serverURL}${uploadOptions.staticURL}/${data.filename}`;
}
return undefined;
},
],
},
},
filename,
mimeType,
filesize,
];
if (uploadOptions.mimeTypes) {
mimeType.validate = mimeTypeValidator(uploadOptions.mimeTypes);
}
if (uploadOptions.imageSizes) {
uploadFields = uploadFields.concat([
width,
height,
{
name: 'sizes',
label: 'Sizes',
type: 'group',
admin: {
disabled: true,
},
fields: uploadOptions.imageSizes.map((size) => ({
label: size.name,
name: size.name,
type: 'group',
admin: {
disabled: true,
},
fields: [
{
...url,
hooks: {
afterRead: [
({ data }) => {
const sizeFilename = data?.sizes?.[size.name]?.filename;
if (sizeFilename) {
return `${config.serverURL}${uploadOptions.staticURL}/${sizeFilename}`;
}
return undefined;
},
],
},
},
width,
height,
mimeType,
filesize,
filename,
],
})),
},
]);
}
return uploadFields;
};
export default getBaseUploadFields;

View File

@@ -1,6 +1,6 @@
import { PayloadRequest } from '../express/types';
import { Operation } from '../types';
import { HookName, FieldAffectingData } from './config/types';
import { HookName, FieldAffectingData, FieldHook } from './config/types';
type Arguments = {
data: Record<string, unknown>
@@ -10,37 +10,80 @@ type Arguments = {
operation: Operation
fullOriginalDoc: Record<string, unknown>
fullData: Record<string, unknown>
flattenLocales: boolean
isVersion: boolean
}
const hookPromise = async ({
data,
field,
hook,
req,
operation,
type ExecuteHookArguments = {
currentHook: FieldHook
value: unknown
} & Arguments;
const executeHook = async ({
currentHook,
fullOriginalDoc,
fullData,
}: Arguments): Promise<void> => {
const resultingData = data;
operation,
req,
value,
}: ExecuteHookArguments) => {
let hookedValue = await currentHook({
value,
originalDoc: fullOriginalDoc,
data: fullData,
operation,
req,
});
if (typeof hookedValue === 'undefined') {
hookedValue = value;
}
return hookedValue;
};
const hookPromise = async (args: Arguments): Promise<void> => {
const {
field,
hook,
req,
flattenLocales,
data,
} = args;
if (field.hooks && field.hooks[hook]) {
await field.hooks[hook].reduce(async (priorHook, currentHook) => {
await priorHook;
let hookedValue = await currentHook({
value: data[field.name],
originalDoc: fullOriginalDoc,
data: fullData,
operation,
req,
});
const shouldRunHookOnAllLocales = hook === 'afterRead'
&& field.localized
&& (req.locale === 'all' || !flattenLocales)
&& typeof data[field.name] === 'object';
if (typeof hookedValue === 'undefined') {
hookedValue = data[field.name];
}
if (shouldRunHookOnAllLocales) {
const hookPromises = Object.entries(data[field.name]).map(([locale, value]) => (async () => {
const hookedValue = await executeHook({
...args,
currentHook,
value,
});
if (hookedValue !== undefined) {
resultingData[field.name] = hookedValue;
if (hookedValue !== undefined) {
data[field.name][locale] = hookedValue;
}
})());
await Promise.all(hookPromises);
} else {
const hookedValue = await executeHook({
...args,
value: data[field.name],
currentHook,
});
if (hookedValue !== undefined) {
data[field.name] = hookedValue;
}
}
}, Promise.resolve());
}

View File

@@ -19,13 +19,15 @@ type Arguments = {
unflattenLocales?: boolean
originalDoc?: Record<string, unknown>
docWithLocales?: Record<string, unknown>
id?: string
id?: string | number
showHiddenFields?: boolean
depth?: number
currentDepth?: number
isVersion?: boolean
skipValidation?: boolean
}
export default async function performFieldOperations(this: Payload, entityConfig: SanitizedCollectionConfig | SanitizedGlobalConfig, args: Arguments): Promise<{ [key: string]: unknown }> {
export default async function performFieldOperations(this: Payload, entityConfig: SanitizedCollectionConfig | SanitizedGlobalConfig, args: Arguments): Promise<any> {
const {
data,
originalDoc: fullOriginalDoc,
@@ -42,6 +44,8 @@ export default async function performFieldOperations(this: Payload, entityConfig
flattenLocales,
unflattenLocales = false,
showHiddenFields = false,
isVersion = false,
skipValidation = false,
} = args;
const fullData = deepCopyObject(data);
@@ -101,6 +105,8 @@ export default async function performFieldOperations(this: Payload, entityConfig
unflattenLocaleActions,
transformActions,
docWithLocales,
isVersion,
skipValidation,
});
if (hook === 'afterRead') {

View File

@@ -42,10 +42,10 @@ const populate = async ({
let populatedRelationship;
if (depth && currentDepth <= depth) {
populatedRelationship = await payload.operations.collections.findByID({
populatedRelationship = await payload.findByID({
req,
collection: relatedCollection,
id: idString,
collection: relatedCollection.config.slug,
id: idString as string,
currentDepth: currentDepth + 1,
overrideAccess,
disableErrors: true,

View File

@@ -19,7 +19,7 @@ type Arguments = {
operation: Operation
overrideAccess: boolean
req: PayloadRequest
id?: string
id?: string | number
relationshipPopulations: (() => Promise<void>)[]
depth: number
currentDepth: number
@@ -36,6 +36,7 @@ type Arguments = {
transformActions: (() => void)[]
docWithLocales?: Record<string, any>
skipValidation?: boolean
isVersion: boolean
}
const traverseFields = (args: Arguments): void => {
@@ -68,6 +69,7 @@ const traverseFields = (args: Arguments): void => {
transformActions,
docWithLocales = {},
skipValidation,
isVersion,
} = args;
fields.forEach((field) => {
@@ -226,6 +228,8 @@ const traverseFields = (args: Arguments): void => {
operation,
fullOriginalDoc,
fullData,
flattenLocales,
isVersion,
}));
}