singularizes Upload and User
This commit is contained in:
11
src/auth/baseFields.js
Normal file
11
src/auth/baseFields.js
Normal 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
23
src/auth/init.js
Normal 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;
|
||||
@@ -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',
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
@@ -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());
|
||||
|
||||
0
src/collections/upload.js
Normal file
0
src/collections/upload.js
Normal 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);
|
||||
}
|
||||
|
||||
@@ -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.`);
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
88
src/index.js
88
src/index.js
@@ -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);
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
8
src/uploads/baseImageFields.js
Normal file
8
src/uploads/baseImageFields.js
Normal file
@@ -0,0 +1,8 @@
|
||||
export default [{
|
||||
sizes: [{
|
||||
name: { type: String },
|
||||
height: { type: Number },
|
||||
width: { type: Number },
|
||||
_id: false,
|
||||
}],
|
||||
}];
|
||||
9
src/uploads/baseUploadFields.js
Normal file
9
src/uploads/baseUploadFields.js
Normal file
@@ -0,0 +1,9 @@
|
||||
export default [
|
||||
{
|
||||
name: 'filename',
|
||||
label: 'Filename',
|
||||
type: 'input',
|
||||
unique: true,
|
||||
required: true,
|
||||
},
|
||||
];
|
||||
@@ -1,19 +0,0 @@
|
||||
export default {
|
||||
fields: [
|
||||
{
|
||||
name: 'sizes',
|
||||
type: 'repeater',
|
||||
id: false,
|
||||
fields: [
|
||||
{
|
||||
name: 'height',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
name: 'width',
|
||||
type: 'number',
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user