Skip to content
Snippets Groups Projects
Commit fdd0d8e0 authored by Yannis Barlas's avatar Yannis Barlas
Browse files

feat(*): dropped connectors

parent 0a66149d
No related branches found
No related tags found
1 merge request!123v4
......@@ -9,20 +9,20 @@ const {
not,
} = require('graphql-shield')
const User = require('./src/models/user/user.model')
const isAuthenticated = rule()(async (parent, args, ctx, info) => {
return !!ctx.user
})
const isAdmin = rule()(
async (parent, args, { user: userId, connectors: { User } }, info) => {
if (!userId) {
return false
}
const isAdmin = rule()(async (parent, args, { user: userId }, info) => {
if (!userId) {
return false
}
const user = await User.model.findById(userId)
return user.admin
},
)
const user = await User.model.findById(userId)
return user.admin
})
module.exports = {
rule,
......
const { ref, val } = require('objection')
const { NotFoundError } = require('../errors')
const notFoundError = (property, value, className) =>
new NotFoundError(`Object not found: ${className} with ${property} ${value}`)
// create a function which creates a new entity and performs authorization checks
const createCreator =
(entityName, EntityModel) => async (input, ctx, options) => {
await ctx.helpers.can(ctx.user, 'create', entityName)
const entity = new EntityModel(input)
entity.setOwners([ctx.user])
if (entity.owners) {
/* eslint-disable-next-line no-param-reassign */
input.owners = entity.owners
}
// Filter input based on authorization
const inputFilter = await ctx.helpers.can(ctx.user, 'create', entity)
const filteredInput = inputFilter(input)
let query = EntityModel.query().insertGraphAndFetch(filteredInput, options)
query = options && options.eager ? query.eager(options.eager) : query
const output = await query
// Filter output based on authorization
const outputFilter = await ctx.helpers.canKnowAbout(ctx.user, output)
return outputFilter(output)
}
// create a function which deletes an entity and performs authorization checks
const deleteCreator = (entityName, EntityModel) => async (id, ctx) => {
await ctx.helpers.can(ctx.user, 'delete', entityName)
const entity = await EntityModel.find(id)
const outputFilter = await ctx.helpers.canKnowAbout(ctx.user, entity)
await ctx.helpers.can(ctx.user, 'delete', entity)
return outputFilter(await entity.delete())
}
// create a function which updates a new entity and performs authorization checks
const updateCreator =
(entityName, EntityModel) => async (id, update, ctx, options) => {
await ctx.helpers.can(ctx.user, 'update', entityName)
const entity = await EntityModel.find(id)
const outputFilter = await ctx.helpers.canKnowAbout(ctx.user, entity)
const currentAndUpdate = { current: entity, update }
const updateFilter = await ctx.helpers.can(
ctx.user,
'update',
currentAndUpdate,
)
const filteredUpdate = updateFilter(update)
// The default is data consistency / data loss minimizing
/* eslint-disable-next-line no-param-reassign */
options = { relate: true, unrelate: true, ...options }
let query = EntityModel.query().upsertGraphAndFetch(
{
id,
...filteredUpdate,
},
options,
)
query = options && options.eager ? query.eager(options.eager) : query
const updated = await query
return outputFilter(updated)
}
// create a function which fetches all entities of the
// given model and performs authorization checks
const fetchAllCreator =
(entityName, EntityModel) => async (where, ctx, options) => {
await ctx.helpers.can(ctx.user, 'read', entityName)
let query
if (where) {
const { _json } = where
/* eslint-disable-next-line no-param-reassign, no-underscore-dangle */
delete where._json
query = EntityModel.query().where(where)
// Add appropriate JSON conditionals
if (_json) {
_json.forEach(condition => {
query = query.where(
ref(condition.ref),
'=',
val(condition.value).castJson(),
)
})
}
const { _relations } = where
/* eslint-disable-next-line no-param-reassign, no-underscore-dangle */
delete where._relations
// Add conditionals for related ids
if (_relations) {
_relations.forEach(condition => {
if (condition.ids) {
condition.ids.forEach((id, index) => {
const alias = `${condition.relation}_${index}`
query = query
.joinRelated(`${condition.relation} as ${alias}`)
.where(`${alias}.id`, id)
})
} else if (condition.object) {
// eslint-disable-next-line no-restricted-syntax
for (const [key, value] of Object.entries(condition.object)) {
query = query
.joinRelated(condition.relation)
.where(`${condition.relation}.${key}`, value)
}
}
})
}
} else {
query = EntityModel.query()
}
query = options && options.eager ? query.eager(options.eager) : query
const entities = await query
return ctx.helpers.filterAll(ctx.user, entities)
}
// create a function which fetches by ID a single entity
// of the given model and performs authorization checks
const fetchOneCreator =
(entityName, EntityModel) => async (id, ctx, options) => {
await ctx.helpers.can(ctx.user, 'read', entityName)
const entity = await ctx.loaders[entityName].load(id)
if (!entity) {
throw notFoundError('id', id, entityName)
}
const outputFilter = await ctx.helpers.canKnowAbout(ctx.user, entity)
return outputFilter(entity)
}
// create a function which fetches a number of entities by ID
// and delegates authorization checks
const fetchSomeCreator = fetchOne => (ids, ctx) =>
ids ? Promise.all(ids.map(id => fetchOne(id, ctx))) : []
const fetchRelatedCreator =
(entityName, EntityModel) => async (id, relation, where, ctx) => {
let entities
const entity = await ctx.loaders[entityName].load(id)
if (where) {
entities = await entity.$relatedQuery(relation).where(where)
} else {
entities = await entity.$relatedQuery(relation)
}
if (Array.isArray(entities)) {
return ctx.helpers.filterAll(ctx.user, entities)
}
if (entities) {
const outputFilter = await ctx.helpers.canKnowAbout(ctx.user, entities)
return outputFilter(entities)
}
return []
}
// create a connector object with fetchers for all, one and some
module.exports = function connector(entityName, EntityModel) {
const create = createCreator(entityName, EntityModel)
const del = deleteCreator(entityName, EntityModel)
const update = updateCreator(entityName, EntityModel)
const fetchAll = fetchAllCreator(entityName, EntityModel)
const fetchOne = fetchOneCreator(entityName, EntityModel)
const fetchSome = fetchSomeCreator(fetchOne)
const fetchRelated = fetchRelatedCreator(entityName, EntityModel)
return {
create,
delete: del,
update,
fetchAll,
fetchOne,
fetchSome,
fetchRelated,
model: EntityModel,
}
}
const config = require('config')
const connector = require('./connector')
const tryRequireRelative = require('../tryRequireRelative')
const connectors = {}
// merge in component connectors, recursively
function getConnectorsRecursively(componentName) {
const component = tryRequireRelative(componentName)
// Backwards compatible for single model syntax
if (component.extending) {
getConnectorsRecursively(component.extending)
}
if (component.modelName) {
connectors[component.modelName] = connector(
component.modelName,
component.model,
)
}
// It is currently not possible to extend a component
// that has multiple models. But models in a multiple
// component model can extend other single model components.
if (component.models) {
component.models.forEach(model => {
if (model.extending) {
getConnectorsRecursively(model.extending)
}
connectors[model.modelName] = connector(model.modelName, model.model)
})
}
}
// recursively merge in component types and resolvers
if (config.has('pubsweet.components')) {
config.get('pubsweet.components').forEach(componentName => {
getConnectorsRecursively(componentName)
})
}
module.exports = connectors
......@@ -11,8 +11,6 @@ const { token } = require('../authentication')
module.exports = {
addSubscriptions: server => {
/* eslint-disable-next-line global-require */
const connectors = require('../connectors')
/* eslint-disable-next-line global-require */
const helpers = require('../authorization')
......@@ -33,7 +31,7 @@ module.exports = {
reject(new Error('Bad auth token'))
}
resolve({ user: id, connectors, helpers })
resolve({ user: id, helpers })
})
})
},
......
......@@ -13,7 +13,6 @@ const errors = require('./errors')
const logger = require('./logger')
const helpers = require('./authorization')
const loaders = require('./graphql/loaders')
const connectors = require('./connectors')
const schema = require('./graphqlSchema')
const isDevelopment = process.env.NODE_ENV === 'development'
......@@ -36,7 +35,6 @@ const createGraphQLServer = testUserContext => {
schema,
context: ({ req, res }) => ({
helpers,
connectors,
user: testUserContext || req.user,
loaders: createdLoaders,
req,
......
......@@ -16,7 +16,7 @@ const logErrorTask = str => {
}
const logInit = str => {
logger.info(chalk.yellow(`\n${PICKAXE} ${str} ${PICKAXE}`))
logger.info(chalk.yellow(`\n${PICKAXE} ${str} ${PICKAXE}`))
}
const logSuccess = str => {
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment