add hook types
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import crypto from 'crypto';
|
||||
import { AfterForgotPasswordHook, BeforeOperationHook } from '../../collections/config/types';
|
||||
import { APIError } from '../../errors';
|
||||
|
||||
async function forgotPassword(incomingArgs) {
|
||||
const { config, sendEmail: email } = this;
|
||||
|
||||
if (!Object.prototype.hasOwnProperty.call(incomingArgs.data, 'email')) {
|
||||
throw new APIError('Missing email.');
|
||||
throw new APIError('Missing email.', 400);
|
||||
}
|
||||
|
||||
let args = incomingArgs;
|
||||
@@ -14,7 +15,7 @@ async function forgotPassword(incomingArgs) {
|
||||
// beforeOperation - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => {
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook, hook: BeforeOperationHook) => {
|
||||
await priorHook;
|
||||
|
||||
args = (await hook({
|
||||
@@ -38,7 +39,7 @@ async function forgotPassword(incomingArgs) {
|
||||
// Forget password
|
||||
// /////////////////////////////////////
|
||||
|
||||
let token = crypto.randomBytes(20);
|
||||
let token: string | Buffer = crypto.randomBytes(20);
|
||||
token = token.toString('hex');
|
||||
|
||||
const user = await Model.findOne({ email: data.email.toLowerCase() });
|
||||
@@ -90,7 +91,7 @@ async function forgotPassword(incomingArgs) {
|
||||
// afterForgotPassword - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterForgotPassword.reduce(async (priorHook, hook) => {
|
||||
await collectionConfig.hooks.afterForgotPassword.reduce(async (priorHook: AfterForgotPasswordHook, hook: AfterForgotPasswordHook) => {
|
||||
await priorHook;
|
||||
await hook({ args });
|
||||
}, Promise.resolve());
|
||||
|
||||
@@ -3,6 +3,7 @@ import { AuthenticationError, LockedAuth } from '../../errors';
|
||||
import getCookieExpiration from '../../utilities/getCookieExpiration';
|
||||
import isLocked from '../isLocked';
|
||||
import removeInternalFields from '../../utilities/removeInternalFields';
|
||||
import { BeforeLoginHook, BeforeOperationHook } from '../../collections/config/types';
|
||||
|
||||
async function login(incomingArgs) {
|
||||
const { config, operations, secret } = this;
|
||||
@@ -13,7 +14,7 @@ async function login(incomingArgs) {
|
||||
// beforeOperation - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => {
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook, hook: BeforeOperationHook) => {
|
||||
await priorHook;
|
||||
|
||||
args = (await hook({
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { BeforeOperationHook } from '../../collections/config/types';
|
||||
import { Forbidden } from '../../errors';
|
||||
import getCookieExpiration from '../../utilities/getCookieExpiration';
|
||||
|
||||
@@ -9,7 +10,7 @@ async function refresh(incomingArgs) {
|
||||
// beforeOperation - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => {
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook, hook: BeforeOperationHook) => {
|
||||
await priorHook;
|
||||
|
||||
args = (await hook({
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
import { Access, Hook } from '../../config/types';
|
||||
/* eslint-disable no-use-before-define */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { Access } from '../../config/types';
|
||||
import { Field } from '../../fields/config/types';
|
||||
import { PayloadRequest } from '../../express/types/payloadRequest';
|
||||
|
||||
export type ImageSize = {
|
||||
name: string,
|
||||
width: number,
|
||||
height: number,
|
||||
crop: string, // comes from sharp package
|
||||
};
|
||||
|
||||
export type Collection = {
|
||||
slug: string;
|
||||
labels?: {
|
||||
@@ -22,18 +17,17 @@ export type Collection = {
|
||||
components?: any;
|
||||
};
|
||||
hooks?: {
|
||||
beforeOperation?: Hook[];
|
||||
beforeValidate?: Hook[];
|
||||
beforeChange?: Hook[];
|
||||
afterChange?: Hook[];
|
||||
beforeRead?: Hook[];
|
||||
afterRead?: Hook[];
|
||||
beforeDelete?: Hook[];
|
||||
afterDelete?: Hook[];
|
||||
beforeLogin?: Hook[];
|
||||
afterLogin?: Hook[];
|
||||
afterForgotPassword?: Hook[];
|
||||
forgotPassword?: Hook[];
|
||||
beforeOperation?: BeforeOperationHook[];
|
||||
beforeValidate?: BeforeValidateHook[];
|
||||
beforeChange?: BeforeChangeHook[];
|
||||
afterChange?: AfterChangeHook[];
|
||||
beforeRead?: BeforeReadHook[];
|
||||
afterRead?: AfterReadHook[];
|
||||
beforeDelete?: BeforeDeleteHook[];
|
||||
afterDelete?: AfterDeleteHook[];
|
||||
beforeLogin?: BeforeLoginHook[];
|
||||
afterLogin?: AfterLoginHook[];
|
||||
afterForgotPassword?: AfterForgotPasswordHook[];
|
||||
};
|
||||
access?: {
|
||||
create?: Access;
|
||||
@@ -59,11 +53,11 @@ export type Collection = {
|
||||
}
|
||||
| boolean;
|
||||
forgotPassword?: {
|
||||
generateEmailHTML?: (args?: {token?: string, email?: string, req?: PayloadRequest}) => string,
|
||||
generateEmailSubject?: (args?: {req?: PayloadRequest}) => string,
|
||||
generateEmailHTML?: (args?: { token?: string, email?: string, req?: PayloadRequest }) => string,
|
||||
generateEmailSubject?: (args?: { req?: PayloadRequest }) => string,
|
||||
}
|
||||
};
|
||||
config: {[key: string]: any};
|
||||
config: { [key: string]: any };
|
||||
upload: {
|
||||
imageSizes: ImageSize[];
|
||||
staticURL: string;
|
||||
@@ -71,3 +65,83 @@ export type Collection = {
|
||||
adminThumbnail?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type ImageSize = {
|
||||
name: string,
|
||||
width: number,
|
||||
height: number,
|
||||
crop: string, // comes from sharp package
|
||||
};
|
||||
|
||||
// Hooks
|
||||
|
||||
export type HookOperationType =
|
||||
| 'create'
|
||||
| 'read'
|
||||
| 'update'
|
||||
| 'delete'
|
||||
| 'refresh'
|
||||
| 'login'
|
||||
| 'forgotPassword';
|
||||
|
||||
export type BeforeOperationHook = (args?: {
|
||||
args?: any;
|
||||
operation: HookOperationType;
|
||||
}) => any;
|
||||
|
||||
export type BeforeValidateHook = (args?: {
|
||||
data?: any;
|
||||
req?: PayloadRequest;
|
||||
operation: 'create' | 'update';
|
||||
originalDoc?: any; // undefined on 'create' operation
|
||||
}) => any;
|
||||
|
||||
export type BeforeChangeHook = (args?: {
|
||||
data: any;
|
||||
req: PayloadRequest;
|
||||
operation: 'create' | 'update'
|
||||
originalDoc?: any; // undefined on 'create' operation
|
||||
}) => any;
|
||||
|
||||
export type AfterChangeHook = (args?: {
|
||||
doc: any;
|
||||
req: PayloadRequest;
|
||||
operation: 'create' | 'update';
|
||||
}) => any;
|
||||
|
||||
export type BeforeReadHook = (args?: {
|
||||
doc: any;
|
||||
req: PayloadRequest;
|
||||
query: { [key: string]: any };
|
||||
}) => any;
|
||||
|
||||
export type AfterReadHook = (args?: {
|
||||
doc: any;
|
||||
req: PayloadRequest;
|
||||
query: { [key: string]: any };
|
||||
}) => any;
|
||||
|
||||
export type BeforeDeleteHook = (args?: {
|
||||
req: PayloadRequest;
|
||||
id: string;
|
||||
}) => any;
|
||||
|
||||
export type AfterDeleteHook = (args?: {
|
||||
req: PayloadRequest;
|
||||
id: string;
|
||||
doc: any;
|
||||
}) => any;
|
||||
|
||||
export type BeforeLoginHook = (args?: {
|
||||
req: PayloadRequest;
|
||||
}) => any;
|
||||
|
||||
export type AfterLoginHook = (args?: {
|
||||
req: PayloadRequest;
|
||||
user: any;
|
||||
token: string;
|
||||
}) => any;
|
||||
|
||||
export type AfterForgotPasswordHook = (args?: {
|
||||
args?: any;
|
||||
}) => any;
|
||||
|
||||
@@ -2,13 +2,17 @@ import mongoose from 'mongoose';
|
||||
import express from 'express';
|
||||
import passport from 'passport';
|
||||
import passportLocalMongoose from 'passport-local-mongoose';
|
||||
const LocalStrategy = require('passport-local').Strategy;
|
||||
import Passport from 'passport-local';
|
||||
import { UpdateQuery } from 'mongodb';
|
||||
import apiKeyStrategy from '../auth/strategies/apiKey';
|
||||
import buildSchema from './buildSchema';
|
||||
import bindCollectionMiddleware from './bindCollection';
|
||||
import { Collection } from './config/types';
|
||||
|
||||
function registerCollections() {
|
||||
this.config.collections = this.config.collections.map((collection) => {
|
||||
const LocalStrategy = Passport.Strategy;
|
||||
|
||||
export default function registerCollections(): void {
|
||||
this.config.collections = this.config.collections.map((collection: Collection) => {
|
||||
const formattedCollection = collection;
|
||||
|
||||
const schema = buildSchema(formattedCollection, this.config);
|
||||
@@ -32,7 +36,8 @@ function registerCollections() {
|
||||
}, cb);
|
||||
}
|
||||
|
||||
const updates = { $inc: { loginAttempts: 1 } };
|
||||
type LoginSchema = { loginAttempts: number; };
|
||||
const updates: UpdateQuery<LoginSchema> = { $inc: { loginAttempts: 1 } };
|
||||
// Lock the account if at max attempts and not already locked
|
||||
if (this.loginAttempts + 1 >= maxLoginAttempts && !this.isLocked) {
|
||||
updates.$set = { lockUntil: Date.now() + lockTime };
|
||||
@@ -151,5 +156,3 @@ function registerCollections() {
|
||||
return formattedCollection;
|
||||
});
|
||||
}
|
||||
|
||||
export default registerCollections;
|
||||
|
||||
@@ -12,6 +12,7 @@ import getImageSize from '../../uploads/getImageSize';
|
||||
import imageMIMETypes from '../../uploads/imageMIMETypes';
|
||||
|
||||
import sendVerificationEmail from '../../auth/sendVerificationEmail';
|
||||
import { AfterChangeHook, BeforeOperationHook, BeforeValidateHook } from '../config/types';
|
||||
|
||||
async function create(incomingArgs) {
|
||||
const { performFieldOperations, config } = this;
|
||||
@@ -22,7 +23,7 @@ async function create(incomingArgs) {
|
||||
// beforeOperation - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => {
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook, hook: BeforeOperationHook) => {
|
||||
await priorHook;
|
||||
|
||||
args = (await hook({
|
||||
@@ -73,7 +74,7 @@ async function create(incomingArgs) {
|
||||
// beforeValidate - Collections
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
|
||||
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook: BeforeValidateHook, hook: BeforeValidateHook) => {
|
||||
await priorHook;
|
||||
|
||||
data = (await hook({
|
||||
@@ -214,7 +215,7 @@ async function create(incomingArgs) {
|
||||
// afterChange - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
|
||||
await collectionConfig.hooks.afterChange.reduce(async (priorHook: AfterChangeHook, hook: AfterChangeHook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
|
||||
@@ -5,6 +5,7 @@ import removeInternalFields from '../../utilities/removeInternalFields';
|
||||
import { NotFound, Forbidden, ErrorDeletingFile } from '../../errors';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import fileExists from '../../uploads/fileExists';
|
||||
import { BeforeOperationHook } from '../config/types';
|
||||
|
||||
async function deleteQuery(incomingArgs) {
|
||||
let args = incomingArgs;
|
||||
@@ -13,7 +14,7 @@ async function deleteQuery(incomingArgs) {
|
||||
// beforeOperation - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => {
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook, hook: BeforeOperationHook) => {
|
||||
await priorHook;
|
||||
|
||||
args = (await hook({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import removeInternalFields from '../../utilities/removeInternalFields';
|
||||
import { BeforeOperationHook, BeforeReadHook } from '../config/types';
|
||||
|
||||
async function find(incomingArgs) {
|
||||
let args = incomingArgs;
|
||||
@@ -8,7 +9,7 @@ async function find(incomingArgs) {
|
||||
// beforeOperation - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => {
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook, hook: BeforeOperationHook) => {
|
||||
await priorHook;
|
||||
|
||||
args = (await hook({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import memoize from 'micro-memoize';
|
||||
import { BeforeOperationHook } from '../config/types';
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import removeInternalFields from '../../utilities/removeInternalFields';
|
||||
import { Forbidden, NotFound } from '../../errors';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
@@ -11,7 +12,7 @@ async function findByID(incomingArgs) {
|
||||
// beforeOperation - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => {
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook, hook: BeforeOperationHook) => {
|
||||
await priorHook;
|
||||
|
||||
args = (await hook({
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import httpStatus from 'http-status';
|
||||
import deepmerge from 'deepmerge';
|
||||
import path from 'path';
|
||||
import { BeforeOperationHook, BeforeChangeHook, BeforeValidateHook } from '../config/types';
|
||||
|
||||
import removeInternalFields from '../../utilities/removeInternalFields';
|
||||
import overwriteMerge from '../../utilities/overwriteMerge';
|
||||
@@ -12,6 +13,7 @@ import getSafeFilename from '../../uploads/getSafeFilename';
|
||||
|
||||
import resizeAndSave from '../../uploads/imageResizer';
|
||||
|
||||
|
||||
async function update(incomingArgs) {
|
||||
let args = incomingArgs;
|
||||
|
||||
@@ -19,7 +21,7 @@ async function update(incomingArgs) {
|
||||
// beforeOperation - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => {
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook, hook: BeforeOperationHook) => {
|
||||
await priorHook;
|
||||
|
||||
args = (await hook({
|
||||
@@ -111,7 +113,7 @@ async function update(incomingArgs) {
|
||||
// beforeValidate - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
|
||||
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook: BeforeValidateHook, hook: BeforeValidateHook) => {
|
||||
await priorHook;
|
||||
|
||||
data = (await hook({
|
||||
@@ -140,7 +142,7 @@ async function update(incomingArgs) {
|
||||
// beforeChange - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => {
|
||||
await collectionConfig.hooks.beforeChange.reduce(async (priorHook: BeforeChangeHook, hook: BeforeChangeHook) => {
|
||||
await priorHook;
|
||||
|
||||
data = (await hook({
|
||||
|
||||
@@ -47,17 +47,18 @@ export type Access = (args?: any) => boolean;
|
||||
|
||||
export type Config = {
|
||||
admin?: {
|
||||
user?: string
|
||||
user?: string;
|
||||
meta?: {
|
||||
titleSuffix?: string
|
||||
ogImage?: string
|
||||
favicon?: string
|
||||
titleSuffix?: string;
|
||||
ogImage?: string;
|
||||
favicon?: string;
|
||||
}
|
||||
disable?: boolean
|
||||
disable?: boolean;
|
||||
indexHTML?: string;
|
||||
};
|
||||
collections?: Collection[];
|
||||
globals?: Global[];
|
||||
serverURL?: string;
|
||||
serverURL: string;
|
||||
cookiePrefix?: string;
|
||||
csrf?: string[];
|
||||
cors?: string[];
|
||||
@@ -68,7 +69,7 @@ export type Config = {
|
||||
graphQL?: string;
|
||||
graphQLPlayground?: string;
|
||||
};
|
||||
express: {
|
||||
express?: {
|
||||
json: {
|
||||
limit?: number
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import deepmerge from 'deepmerge';
|
||||
import overwriteMerge from '../../utilities/overwriteMerge';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import removeInternalFields from '../../utilities/removeInternalFields';
|
||||
import { AfterChangeHook, BeforeValidateHook } from '../../collections/config/types';
|
||||
|
||||
async function update(args) {
|
||||
const { globals: { Model } } = this;
|
||||
@@ -53,7 +54,7 @@ async function update(args) {
|
||||
// 3. Execute before validate collection hooks
|
||||
// /////////////////////////////////////
|
||||
|
||||
await globalConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
|
||||
await globalConfig.hooks.beforeValidate.reduce(async (priorHook: BeforeValidateHook, hook: BeforeValidateHook) => {
|
||||
await priorHook;
|
||||
|
||||
data = (await hook({
|
||||
@@ -123,7 +124,7 @@ async function update(args) {
|
||||
// 9. Execute after global hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
await globalConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
|
||||
await globalConfig.hooks.afterChange.reduce(async (priorHook: AfterChangeHook, hook: AfterChangeHook) => {
|
||||
await priorHook;
|
||||
|
||||
global = await hook({
|
||||
|
||||
Reference in New Issue
Block a user