singularizes Upload and User

This commit is contained in:
James
2019-12-31 17:38:23 -05:00
parent 9bef5f9f4f
commit 618d6dc19b
23 changed files with 198 additions and 188 deletions

11
src/auth/baseFields.js Normal file
View File

@@ -0,0 +1,11 @@
export default [{
name: 'resetPasswordToken',
// TODO: how should we define a field a string that cannot be seen in the admin panel?
// using type: 'input' for now
type: 'input',
},
{
name: 'resetPasswordExpiration',
type: 'date',
},
];

23
src/auth/init.js Normal file
View File

@@ -0,0 +1,23 @@
import passport from 'passport';
import AnonymousStrategy from 'passport-anonymous';
import jwtStrategy from './jwt';
import initRoutes from '../routes/init';
import authRoutes from './routes';
const initUsers = (User, config, router) => {
passport.use(User.createStrategy());
const { user: userConfig } = config;
if (userConfig.auth.strategy === 'jwt') {
passport.use(jwtStrategy(User));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
}
passport.use(new AnonymousStrategy.Strategy());
router.use('', initRoutes(User));
router.use('', authRoutes(userConfig, User));
};
export default initUsers;

View File

@@ -1,13 +0,0 @@
export default {
fields: [{
name: 'resetPasswordToken',
// TODO: how should we define a field a string that cannot be seen in the admin panel?
// using type: 'input' for now
type: 'input',
},
{
name: 'resetPasswordExpiration',
type: 'date',
}
]
}

View File

@@ -45,7 +45,7 @@ module.exports = (config) => {
output: {
path: '/',
publicPath: '/static',
filename: '[name].js'
filename: '[name].js',
},
devServer: {
historyApiFallback: true,
@@ -58,8 +58,8 @@ module.exports = (config) => {
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
loader: 'babel-loader',
},
},
{
// "oneOf" will traverse all following loaders until one will
@@ -82,7 +82,7 @@ module.exports = (config) => {
// to immediately apply all styles to the DOM.
{
test: /\.(scss|sass)$/,
use: getStyleLoaders({ importLoaders: 2 }, 'sass-loader')
use: getStyleLoaders({ importLoaders: 2 }, 'sass-loader'),
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
@@ -100,14 +100,14 @@ module.exports = (config) => {
name: 'static/media/[name].[hash:8].[ext]',
},
},
]
}
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/client/index.html',
filename: './index.html'
filename: './index.html',
}),
new webpack.HotModuleReplacementPlugin(),
],
@@ -115,8 +115,8 @@ module.exports = (config) => {
alias: {
payload: path.resolve(__dirname, '../../'),
scssOverrides: config.paths.scssOverrides,
customComponents: config.paths.customComponents
}
}
}
config: config.paths.config,
},
},
};
};

View File

@@ -1,18 +1,12 @@
import mongoose from 'mongoose';
import mongooseHidden from 'mongoose-hidden';
import paginate from 'mongoose-paginate-v2';
import autopopulate from 'mongoose-autopopulate';
import buildQueryPlugin from '../mongoose/buildQuery';
import localizationPlugin from '../localization/plugin';
import passwordResetConfig from '../auth/passwordResets/config';
import buildSchema from '../mongoose/schema/buildSchema';
const addSchema = (collection, config) => {
if (collection.auth) {
collection.fields.push(...passwordResetConfig.fields);
}
const schema = buildSchema(collection.fields, config, { timestamps: collection.timestamps });
const buildCollectionSchema = (collection, config, schemaOptions = {}) => {
const schema = buildSchema(collection.fields, config, { timestamps: collection.timestamps, ...schemaOptions });
schema.plugin(paginate)
.plugin(buildQueryPlugin)
@@ -26,10 +20,7 @@ const addSchema = (collection, config) => {
});
}
return {
config: collection,
model: mongoose.model(collection.slug, schema),
};
return schema;
};
export default addSchema;
export default buildCollectionSchema;

View File

@@ -1,8 +1,3 @@
import passport from 'passport';
import AnonymousStrategy from 'passport-anonymous';
import jwtStrategy from '../auth/jwt';
import initRoutes from '../routes/init';
import authRoutes from '../auth/routes';
import {
query, create, findOne, destroy, update,
} from '../mongoose/requestHandlers';
@@ -11,21 +6,6 @@ import setModelLocaleMiddleware from '../localization/setModelLocale';
import { loadPolicy } from '../auth/loadPolicy';
const registerRoutes = ({ model, config }, router) => {
// register passport with model
if (config.auth) {
passport.use(model.createStrategy());
if (config.auth.strategy === 'jwt') {
passport.use(jwtStrategy(model));
passport.serializeUser(model.serializeUser());
passport.deserializeUser(model.deserializeUser());
}
passport.use(new AnonymousStrategy.Strategy());
router.use('', initRoutes(model));
router.use('', authRoutes(config, model));
}
router.all(`/${config.slug}*`,
bindModelMiddleware(model),
setModelLocaleMiddleware());

View File

View File

@@ -1,10 +1,6 @@
import { DuplicateCollection, MissingCollectionLabel, ExistingUser } from '../errors';
export default function validateCollection(collection, collections, userModel) {
if (collection.auth && userModel) {
throw new ExistingUser();
}
import { DuplicateCollection, MissingCollectionLabel } from '../errors';
export default function validateCollection(collection, collections) {
if (!collection.labels.singular) {
throw new MissingCollectionLabel(collection);
}

View File

@@ -1,7 +0,0 @@
import { APIError } from './APIError';
export class ExistingUser extends APIError {
constructor(config) {
super(`Error when registering "${ config.labels.singular }": a user model already exists.`);
}
}

View File

@@ -3,5 +3,4 @@ export { DuplicateCollection } from './DuplicateCollection';
export { DuplicateGlobal } from './DuplicateGlobal';
export { MissingCollectionLabel } from './MissingCollectionLabel';
export { MissingGlobalLabel } from './MissingGlobalLabel';
export { ExistingUser } from './ExistingUser';
export { NotFound } from './NotFound';

View File

@@ -1,12 +1,18 @@
import mongoose from 'mongoose';
import connectMongoose from './init/connectMongoose';
import registerExpressMiddleware from './init/registerExpressMiddleware';
import initUploads from './init/uploads';
import initPassport from './init/passport';
import initCORS from './init/cors';
import initUploads from './init/uploads';
import initWebpack from './init/webpack';
import initUserAuth from './auth/init';
import baseUserFields from './auth/baseFields';
import baseUploadFields from './uploads/baseUploadFields';
import baseImageFields from './uploads/baseImageFields';
import registerUploadRoutes from './uploads/routes';
import registerConfigRoute from './routes/config';
import validateCollection from './collections/validate';
import registerCollectionSchema from './collections/registerSchema';
import buildCollectionSchema from './collections/buildSchema';
import registerCollectionRoutes from './collections/registerRoutes';
import validateGlobals from './globals/validate';
import registerGlobalSchema from './globals/registerSchema';
@@ -16,27 +22,77 @@ class Payload {
collections = {};
constructor(options) {
// Setup & inititalization
connectMongoose(options.config.mongoURL);
registerExpressMiddleware(options);
initPassport(options.app);
initUploads(options);
initCORS(options);
registerConfigRoute(options, this.getCollections, this.getGlobals);
// Bind options, app, router
this.config = options.config;
this.app = options.app;
this.router = options.router;
connectMongoose(options.config.mongoURL);
registerExpressMiddleware(options);
initUploads(options);
initPassport(this.app);
initCORS(options);
registerConfigRoute(options, this.getCollections, this.getGlobals);
// Register and bind required collections
this.registerUser();
this.registerUpload();
if (!this.config.disableAdmin) {
initWebpack(options);
}
// Register custom collections
this.config.collections.forEach((collection) => {
validateCollection(collection, this.collections);
this.collections[collection.slug] = {
model: mongoose.model(collection.slug, buildCollectionSchema(collection, this.config)),
config: collection,
};
registerCollectionRoutes(this.collections[collection.slug], this.router);
});
// Register globals
this.registerGlobals(this.config.globals);
// Enable client webpack
if (!this.config.disableAdmin) initWebpack(options);
}
registerCollection = (collection) => {
validateCollection(collection, this.collections, this.User);
this.collections[collection.slug] = registerCollectionSchema(collection, this.config);
registerCollectionRoutes(this.collections[collection.slug], this.router);
};
registerUser = () => {
this.config.user.fields.push(...baseUserFields);
const userSchema = buildCollectionSchema(this.config.user, this.config);
this.User = mongoose.model(this.config.user.labels.singular, userSchema);
initUserAuth(this.User, this.config, this.router);
registerCollectionRoutes({
model: this.User,
config: this.config.user,
}, this.router);
}
registerUpload = () => {
const uploadSchema = buildCollectionSchema(
this.config.upload,
this.config,
{ discriminatorKey: 'type' },
baseUploadFields,
);
const imageSchema = buildCollectionSchema(
this.config.upload,
this.config,
{ discriminatorKey: 'type' },
{ ...baseUploadFields, ...baseImageFields },
);
this.Upload = mongoose.model(this.config.upload.labels.singular, uploadSchema);
this.Upload.discriminator('image', imageSchema);
registerUploadRoutes({
default: this.Upload,
image: imageSchema,
}, this.config, this.router);
}
registerGlobals = (globals) => {
validateGlobals(globals);

View File

@@ -2,8 +2,8 @@ import { Schema } from 'mongoose';
import fieldToSchemaMap from './fieldToSchemaMap';
import baseFields from './baseFields';
const buildSchema = (configFields, config, options = {}) => {
const fields = { ...baseFields };
const buildSchema = (configFields, config, options = {}, additionalBaseFields = {}) => {
const fields = { ...baseFields, ...additionalBaseFields };
const flexiblefields = [];
configFields.forEach((field) => {

View File

@@ -0,0 +1,8 @@
export default [{
sizes: [{
name: { type: String },
height: { type: Number },
width: { type: Number },
_id: false,
}],
}];

View File

@@ -0,0 +1,9 @@
export default [
{
name: 'filename',
label: 'Filename',
type: 'input',
unique: true,
required: true,
},
];

View File

@@ -1,19 +0,0 @@
export default {
fields: [
{
name: 'sizes',
type: 'repeater',
id: false,
fields: [
{
name: 'height',
type: 'number',
},
{
name: 'width',
type: 'number',
},
],
}
]
}

View File

@@ -1,21 +0,0 @@
import mongoose from 'mongoose';
import localizationPlugin from '../../localization/plugin';
const imageUploadModelLoader = (Upload, config) => {
const ImageSchema = new mongoose.Schema(
{
sizes: [{
name: { type: String },
height: { type: Number },
width: { type: Number },
_id: false,
}],
},
);
ImageSchema.plugin(localizationPlugin, config.localization);
return Upload.discriminator('image', ImageSchema);
};
export default imageUploadModelLoader;

View File

@@ -1,21 +0,0 @@
import mongoose from 'mongoose';
import paginate from 'mongoose-paginate-v2';
import buildQueryPlugin from '../mongoose/buildQuery';
import localizationPlugin from '../localization/plugin';
const uploadModelLoader = (config) => {
const UploadSchema = new mongoose.Schema({
filename: { type: String },
}, {
timestamps: true,
discriminatorKey: 'type',
});
UploadSchema.plugin(paginate);
UploadSchema.plugin(buildQueryPlugin);
UploadSchema.plugin(localizationPlugin, config.localization);
return mongoose.model('Upload', UploadSchema);
};
export default uploadModelLoader;

View File

@@ -2,21 +2,13 @@ import passport from 'passport';
import fileUpload from 'express-fileupload';
import { upload, update } from './requestHandlers';
import uploadMiddleware from './middleware';
import uploadModelLoader from './model';
import imageUploadModelLoader from './images/model';
import setModelLocaleMiddleware from '../localization/setModelLocale';
const uploadRoutes = (config, app, router) => {
const Upload = uploadModelLoader(config);
const UploadModels = {
default: Upload,
image: imageUploadModelLoader(Upload, config),
};
const uploadRoutes = (models, config, router) => {
router.all('/upload*',
fileUpload(),
passport.authenticate('jwt', { session: false }),
uploadMiddleware(config, UploadModels),
uploadMiddleware(config, models),
setModelLocaleMiddleware());
router.route('/upload')