flattens user into collections

This commit is contained in:
James
2020-05-18 16:39:40 -04:00
parent 8809bcb573
commit 098b5be274
64 changed files with 321 additions and 431 deletions

View File

@@ -1,4 +1,3 @@
const mongooseHidden = require('mongoose-hidden');
const paginate = require('mongoose-paginate-v2');
const autopopulate = require('mongoose-autopopulate');
const buildQueryPlugin = require('../mongoose/buildQuery');
@@ -11,8 +10,7 @@ const buildCollectionSchema = (collection, config, schemaOptions = {}) => {
schema.plugin(paginate)
.plugin(buildQueryPlugin)
.plugin(localizationPlugin, config.localization)
.plugin(autopopulate)
.plugin(mongooseHidden());
.plugin(autopopulate);
return schema;
};

View File

@@ -1,13 +1,20 @@
const {
GraphQLString,
GraphQLBoolean,
GraphQLNonNull,
GraphQLInt,
} = require('graphql');
const formatName = require('../../graphql/utilities/formatName');
const {
create, find, findByID, deleteResolver, update,
} = require('./resolvers');
const {
login, me, init, refresh, register, forgotPassword, resetPassword, policies,
} = require('../../auth/graphql/resolvers');
const buildPaginatedListType = require('../../graphql/schema/buildPaginatedListType');
function registerCollections() {
@@ -19,10 +26,12 @@ function registerCollections() {
singular,
plural,
},
fields,
fields: initialFields,
},
} = collection;
const fields = [...initialFields];
const singularLabel = formatName(singular);
let pluralLabel = formatName(plural);
@@ -53,6 +62,14 @@ function registerCollections() {
singularLabel,
);
if (collection.auth) {
fields.push({
name: 'password',
type: 'text',
required: true,
});
}
collection.graphQL.mutationInputType = new GraphQLNonNull(this.buildMutationInputType(
singularLabel,
fields,
@@ -93,14 +110,6 @@ function registerCollections() {
resolve: find(collection),
};
this.Mutation.fields[`create${singularLabel}`] = {
type: collection.graphQL.type,
args: {
data: { type: collection.graphQL.mutationInputType },
},
resolve: create(collection),
};
this.Mutation.fields[`update${singularLabel}`] = {
type: collection.graphQL.type,
args: {
@@ -117,6 +126,90 @@ function registerCollections() {
},
resolve: deleteResolver(collection),
};
if (collection.auth) {
collection.graphQL.jwt = this.buildObjectType(
'JWT',
collection.config.fields.reduce((jwtFields, potentialField) => {
if (potentialField.saveToJWT) {
return [
...jwtFields,
potentialField,
];
}
return jwtFields;
}, [
{
name: 'username',
type: 'text',
required: true,
},
]),
);
this.Query.fields[`policies${singularLabel}`] = {
type: this.buildPoliciesType(),
resolve: policies(this.config, collection),
};
this.Query.fields[`me${singularLabel}`] = {
type: collection.graphQL.jwt,
resolve: me,
};
this.Query.fields[`initialized${singularLabel}`] = {
type: GraphQLBoolean,
resolve: init(collection),
};
this.Mutation.fields[`login${singularLabel}`] = {
type: GraphQLString,
args: {
username: { type: GraphQLString },
password: { type: GraphQLString },
},
resolve: login(this.config, collection),
};
this.Mutation.fields[`register${singularLabel}`] = {
type: collection.graphQL.type,
args: {
data: { type: collection.graphQL.mutationInputType },
},
resolve: register(this.config, collection),
};
this.Mutation.fields[`forgotPassword${singularLabel}`] = {
type: new GraphQLNonNull(GraphQLBoolean),
args: {
username: { type: new GraphQLNonNull(GraphQLString) },
},
resolve: forgotPassword(this.config, collection.Model, this.sendEmail),
};
this.Mutation.fields[`resetPassword${singularLabel}`] = {
type: GraphQLString,
args: {
token: { type: GraphQLString },
password: { type: GraphQLString },
},
resolve: resetPassword(collection),
};
this.Mutation.fields[`refreshToken${singularLabel}`] = {
type: GraphQLString,
resolve: refresh(this.config, collection),
};
} else {
this.Mutation.fields[`create${singularLabel}`] = {
type: collection.graphQL.type,
args: {
data: { type: collection.graphQL.mutationInputType },
},
resolve: create(collection),
};
}
});
}

View File

@@ -1,7 +1,21 @@
const mongoose = require('mongoose');
const mongooseHidden = require('mongoose-hidden')({
hidden: {
salt: true, hash: true, _id: true, __v: true,
},
applyRecursively: true,
});
const passport = require('passport');
const passportLocalMongoose = require('passport-local-mongoose');
const LocalStrategy = require('passport-local').Strategy;
const AnonymousStrategy = require('passport-anonymous');
const jwtStrategy = require('../auth/strategies/jwt');
const apiKeyStrategy = require('../auth/strategies/apiKey');
const collectionRoutes = require('./routes');
const buildSchema = require('./buildSchema');
const sanitize = require('./sanitize');
const baseAuthFields = require('../auth/baseFields');
const authRoutes = require('../auth/routes');
function registerCollections() {
this.config.collections.forEach((collection) => {
@@ -89,14 +103,40 @@ function registerCollections() {
];
}
if (collection.auth) {
formattedCollection.fields = [
...formattedCollection.fields,
...baseAuthFields,
];
}
const schema = buildSchema(formattedCollection, this.config);
if (collection.auth) {
schema.plugin(passportLocalMongoose);
}
schema.plugin(mongooseHidden);
this.collections[formattedCollection.slug] = {
Model: mongoose.model(formattedCollection.slug, schema),
config: sanitize(this.collections, formattedCollection),
};
this.router.use(collectionRoutes(this.collections[formattedCollection.slug]));
if (collection.auth) {
const AuthCollection = this.collections[formattedCollection.slug];
passport.use(new LocalStrategy(AuthCollection.Model.authenticate()));
passport.use(apiKeyStrategy(AuthCollection));
passport.use(jwtStrategy(this.config, AuthCollection.Model));
passport.serializeUser(AuthCollection.Model.serializeUser());
passport.deserializeUser(AuthCollection.Model.deserializeUser());
passport.use(new AnonymousStrategy.Strategy());
this.router.use(authRoutes(AuthCollection, this.config, this.sendEmail));
} else {
this.router.use(collectionRoutes(this.collections[formattedCollection.slug]));
}
});
}

View File

@@ -1,6 +1,6 @@
const mkdirp = require('mkdirp');
const executePolicy = require('../../users/executePolicy');
const executePolicy = require('../../auth/executePolicy');
const executeFieldHooks = require('../../fields/executeHooks');
const { validateCreate } = require('../../fields/validateCreate');

View File

@@ -1,6 +1,6 @@
const fs = require('fs');
const { NotFound, Forbidden } = require('../../errors');
const executePolicy = require('../../users/executePolicy');
const executePolicy = require('../../auth/executePolicy');
const deleteQuery = async (args) => {
try {

View File

@@ -1,5 +1,5 @@
const merge = require('lodash.merge');
const executePolicy = require('../../users/executePolicy');
const executePolicy = require('../../auth/executePolicy');
const executeFieldHooks = require('../../fields/executeHooks');
const find = async (args) => {

View File

@@ -1,5 +1,5 @@
const { Forbidden, NotFound } = require('../../errors');
const executePolicy = require('../../users/executePolicy');
const executePolicy = require('../../auth/executePolicy');
const executeFieldHooks = require('../../fields/executeHooks');
const findByID = async (args) => {

View File

@@ -1,4 +1,4 @@
const executePolicy = require('../../users/executePolicy');
const executePolicy = require('../../auth/executePolicy');
const executeFieldHooks = require('../../fields/executeHooks');
const { NotFound, Forbidden } = require('../../errors');
const validate = require('../../fields/validateUpdate');

View File

@@ -5,7 +5,7 @@
require('isomorphic-fetch');
const faker = require('faker');
const config = require('../../../demo/payload.config');
const { email, password } = require('../../tests/credentials');
const { username, password } = require('../../tests/credentials');
const url = config.serverURL;
@@ -16,9 +16,9 @@ const englishPostDesc = faker.lorem.lines(2);
const spanishPostDesc = faker.lorem.lines(2);
beforeAll(async (done) => {
const response = await fetch(`${url}/api/login`, {
const response = await fetch(`${url}/api/users/login`, {
body: JSON.stringify({
email,
username,
password,
}),
headers: {
@@ -261,7 +261,7 @@ describe('Collections - REST', () => {
it('should include metadata', async () => {
const desc = 'metadataDesc';
for (let i = 0; i < 12; i += 1) {
// eslint-disable-next-line no-await-in-loop
// eslint-disable-next-line no-await-in-loop
await createPost(null, desc);
}