diff --git a/src/routes/activity.ts b/src/routes/activity.ts index 751520d6a7..d73fd3d126 100644 --- a/src/routes/activity.ts +++ b/src/routes/activity.ts @@ -6,24 +6,29 @@ import useCollection from '../middleware/use-collection'; const router = express.Router(); -router.use(useCollection('directus_activity')); - router.get( '/', + useCollection('directus_activity'), sanitizeQuery, asyncHandler(async (req, res) => { - // const records = await ActivityService.readActivities(req.sanitizedQuery); - // return res.json({ - // data: records || null, - // }); + const records = await ActivityService.readActivities(req.sanitizedQuery, { + role: req.role, + }); + + return res.json({ + data: records || null, + }); }) ); router.get( '/:pk', + useCollection('directus_activity'), sanitizeQuery, asyncHandler(async (req, res) => { - const record = await ActivityService.readActivity(req.params.pk, req.sanitizedQuery); + const record = await ActivityService.readActivity(req.params.pk, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: record || null, @@ -33,6 +38,7 @@ router.get( router.post( '/comment', + useCollection('directus_activity'), sanitizeQuery, asyncHandler(async (req, res) => { const primaryKey = await ActivityService.createActivity({ @@ -43,7 +49,9 @@ router.post( user_agent: req.get('user-agent'), }); - const record = await ActivityService.readActivity(primaryKey, req.sanitizedQuery); + const record = await ActivityService.readActivity(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: record || null, @@ -53,15 +61,19 @@ router.post( router.patch( '/comment/:pk', + useCollection('directus_activity'), sanitizeQuery, asyncHandler(async (req, res) => { const primaryKey = await ActivityService.updateActivity(req.params.pk, req.body, { + role: req.role, user: req.user, ip: req.ip, userAgent: req.get('user-agent'), }); - const record = await ActivityService.readActivity(primaryKey, req.sanitizedQuery); + const record = await ActivityService.readActivity(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: record || null, @@ -71,8 +83,10 @@ router.patch( router.delete( '/comment/:pk', + useCollection('directus_activity'), asyncHandler(async (req, res) => { await ActivityService.deleteActivity(req.params.pk, { + role: req.role, user: req.user, ip: req.ip, userAgent: req.get('user-agent'), diff --git a/src/routes/collections.ts b/src/routes/collections.ts index 38d823e1fb..ee4d2b0cb8 100644 --- a/src/routes/collections.ts +++ b/src/routes/collections.ts @@ -31,6 +31,7 @@ router.post( if (error) throw new InvalidPayloadException(error.message); const createdCollection = await CollectionsService.create(req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, @@ -45,8 +46,10 @@ router.get( useCollection('directus_collections'), sanitizeQuery, asyncHandler(async (req, res) => { - // const collections = await CollectionsService.readAll(req.sanitizedQuery); - // res.json({ data: collections || null }); + const collections = await CollectionsService.readAll(req.sanitizedQuery, { + role: req.role, + }); + res.json({ data: collections || null }); }) ); @@ -61,7 +64,8 @@ router.get( const collection = await CollectionsService.readOne( req.params.collection, - req.sanitizedQuery + req.sanitizedQuery, + { role: req.role } ); res.json({ data: collection || null }); }) @@ -76,6 +80,7 @@ router.delete( } await CollectionsService.deleteCollection(req.params.collection, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, diff --git a/src/routes/fields.ts b/src/routes/fields.ts index bdcd2be6e3..768a97d48f 100644 --- a/src/routes/fields.ts +++ b/src/routes/fields.ts @@ -10,10 +10,15 @@ import useCollection from '../middleware/use-collection'; const router = Router(); -router.use(useCollection('directus_fields')); +/** + * @TODO + * + * Add accountability / permissions handling to fields + */ router.get( '/', + useCollection('directus_fields'), asyncHandler(async (req, res) => { const fields = await FieldsService.readAll(); return res.json({ data: fields || null }); @@ -22,6 +27,7 @@ router.get( router.get( '/:collection', + useCollection('directus_fields'), validateCollection, asyncHandler(async (req, res) => { const fields = await FieldsService.readAll(req.collection); @@ -31,6 +37,7 @@ router.get( router.get( '/:collection/:field', + useCollection('directus_fields'), validateCollection, asyncHandler(async (req, res) => { const exists = await schemaInspector.hasColumn(req.collection, req.params.field); @@ -54,6 +61,7 @@ const newFieldSchema = Joi.object({ router.post( '/:collection', + useCollection('directus_fields'), validateCollection, asyncHandler(async (req, res) => { const { error } = newFieldSchema.validate(req.body); @@ -65,6 +73,7 @@ router.post( const field: Partial = req.body; const createdField = await FieldsService.createField(req.collection, field, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, diff --git a/src/routes/files.ts b/src/routes/files.ts index 15436da535..427db82d33 100644 --- a/src/routes/files.ts +++ b/src/routes/files.ts @@ -56,11 +56,14 @@ const multipartHandler = (operation: 'create' | 'update') => try { if (operation === 'create') { const pk = await FilesService.createFile(payload, fileStream, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const file = await FilesService.readFile(pk, req.sanitizedQuery); + const file = await FilesService.readFile(pk, req.sanitizedQuery, { + role: req.role, + }); savedFiles.push(file); } else { @@ -68,13 +71,16 @@ const multipartHandler = (operation: 'create' | 'update') => req.params.pk, payload, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }, fileStream ); - const file = await FilesService.readFile(pk, req.sanitizedQuery); + const file = await FilesService.readFile(pk, req.sanitizedQuery, { + role: req.role, + }); savedFiles.push(file); } @@ -100,8 +106,8 @@ router.get( '/', sanitizeQuery, asyncHandler(async (req, res) => { - // const records = await FilesService.readFiles(req.sanitizedQuery); - // return res.json({ data: records || null }); + const records = await FilesService.readFiles(req.sanitizedQuery, { role: req.role }); + return res.json({ data: records || null }); }) ); @@ -109,7 +115,9 @@ router.get( '/:pk', sanitizeQuery, asyncHandler(async (req, res) => { - const record = await FilesService.readFile(req.params.pk, req.sanitizedQuery); + const record = await FilesService.readFile(req.params.pk, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: record || null }); }) ); @@ -124,11 +132,12 @@ router.patch( file = await multipartHandler('update')(req, res, next); } else { const pk = await FilesService.updateFile(req.params.pk, req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - file = await FilesService.readFile(pk, req.sanitizedQuery); + file = await FilesService.readFile(pk, req.sanitizedQuery, { role: req.role }); } return res.status(200).json({ data: file || null }); @@ -139,6 +148,7 @@ router.delete( '/:pk', asyncHandler(async (req, res) => { await FilesService.deleteFile(req.params.pk, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, diff --git a/src/routes/folders.ts b/src/routes/folders.ts index 5d60b7dd5f..1d2873fa5b 100644 --- a/src/routes/folders.ts +++ b/src/routes/folders.ts @@ -12,12 +12,15 @@ router.post( '/', asyncHandler(async (req, res) => { const primaryKey = await FoldersService.createFolder(req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const record = await FoldersService.readFolder(primaryKey, req.sanitizedQuery); + const record = await FoldersService.readFolder(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: record || null }); }) ); @@ -26,8 +29,8 @@ router.get( '/', sanitizeQuery, asyncHandler(async (req, res) => { - // const records = await FoldersService.readFolders(req.sanitizedQuery); - // return res.json({ data: records || null }); + const records = await FoldersService.readFolders(req.sanitizedQuery, { role: req.role }); + return res.json({ data: records || null }); }) ); @@ -35,7 +38,9 @@ router.get( '/:pk', sanitizeQuery, asyncHandler(async (req, res) => { - const record = await FoldersService.readFolder(req.params.pk, req.sanitizedQuery); + const record = await FoldersService.readFolder(req.params.pk, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: record || null }); }) ); @@ -45,12 +50,15 @@ router.patch( sanitizeQuery, asyncHandler(async (req, res) => { const primaryKey = await FoldersService.updateFolder(req.params.pk, req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const record = await FoldersService.readFolder(primaryKey, req.sanitizedQuery); + const record = await FoldersService.readFolder(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: record || null }); }) @@ -60,6 +68,7 @@ router.delete( '/:pk', asyncHandler(async (req, res) => { await FoldersService.deleteFolder(req.params.pk, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, diff --git a/src/routes/items.ts b/src/routes/items.ts index acb2fd8f15..e761e7c424 100644 --- a/src/routes/items.ts +++ b/src/routes/items.ts @@ -4,9 +4,7 @@ import * as ItemsService from '../services/items'; import sanitizeQuery from '../middleware/sanitize-query'; import collectionExists from '../middleware/collection-exists'; import * as MetaService from '../services/meta'; -import * as PermissionsService from '../services/permissions'; import { RouteNotFoundException } from '../exceptions'; -import getASTFromQuery from '../utils/get-ast-from-query'; const router = express.Router(); @@ -20,12 +18,15 @@ router.post( } const primaryKey = await ItemsService.createItem(req.collection, req.body, { + user: req.user, + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), - user: req.user, }); - const item = await ItemsService.readItem(req.collection, primaryKey, req.sanitizedQuery); + const item = await ItemsService.readItem(req.collection, primaryKey, req.sanitizedQuery, { + role: req.role, + }); res.json({ data: item || null }); }) @@ -36,16 +37,10 @@ router.get( collectionExists, sanitizeQuery, asyncHandler(async (req, res) => { - let ast = await getASTFromQuery(req.role, req.collection, req.sanitizedQuery); - - console.log(JSON.stringify(ast, null, 2)); - - ast = await PermissionsService.processAST(req.role, ast); - const [records, meta] = await Promise.all([ req.single - ? ItemsService.readSingleton(req.collection, ast) - : ItemsService.readItems(req.collection, ast), + ? ItemsService.readSingleton(req.collection, req.sanitizedQuery, { role: req.role }) + : ItemsService.readItems(req.collection, req.sanitizedQuery, { role: req.role }), MetaService.getMetaForQuery(req.collection, req.sanitizedQuery), ]); @@ -68,7 +63,8 @@ router.get( const record = await ItemsService.readItem( req.collection, req.params.pk, - req.sanitizedQuery + req.sanitizedQuery, + { role: req.role } ); return res.json({ @@ -87,14 +83,17 @@ router.patch( } await ItemsService.upsertSingleton(req.collection, req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - // const item = await ItemsService.readSingleton(req.collection, req.sanitizedQuery); + const item = await ItemsService.readSingleton(req.collection, req.sanitizedQuery, { + role: req.role, + }); - // return res.json({ data: item || null }); + return res.json({ data: item || null }); }) ); @@ -108,12 +107,15 @@ router.patch( } const primaryKey = await ItemsService.updateItem(req.collection, req.params.pk, req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const item = await ItemsService.readItem(req.collection, primaryKey, req.sanitizedQuery); + const item = await ItemsService.readItem(req.collection, primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) @@ -124,6 +126,7 @@ router.delete( collectionExists, asyncHandler(async (req, res) => { await ItemsService.deleteItem(req.collection, req.params.pk, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, diff --git a/src/routes/permissions.ts b/src/routes/permissions.ts index 1e5a2ec34d..bc3f8a93ed 100644 --- a/src/routes/permissions.ts +++ b/src/routes/permissions.ts @@ -6,17 +6,21 @@ import useCollection from '../middleware/use-collection'; const router = express.Router(); +router.use(useCollection('directus_permissions')); + router.post( '/', - useCollection('directus_permissions'), asyncHandler(async (req, res) => { const primaryKey = await PermissionsService.createPermission(req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const item = await PermissionsService.readPermission(primaryKey, req.sanitizedQuery); + const item = await PermissionsService.readPermission(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) @@ -24,22 +28,23 @@ router.post( router.get( '/', - useCollection('directus_permissions'), sanitizeQuery, asyncHandler(async (req, res) => { - const item = await PermissionsService.readPermissions(req.sanitizedQuery); - // return res.json({ data: item || null }); + const item = await PermissionsService.readPermissions(req.sanitizedQuery, { + role: req.role, + }); + return res.json({ data: item || null }); }) ); router.get( '/:pk', - useCollection('directus_permissions'), sanitizeQuery, asyncHandler(async (req, res) => { const record = await PermissionsService.readPermission( Number(req.params.pk), - req.sanitizedQuery + req.sanitizedQuery, + { role: req.role } ); return res.json({ data: record || null }); }) @@ -47,19 +52,21 @@ router.get( router.patch( '/:pk', - useCollection('directus_permissions'), asyncHandler(async (req, res) => { const primaryKey = await PermissionsService.updatePermission( Number(req.params.pk), req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, } ); - const item = await PermissionsService.readPermission(primaryKey, req.sanitizedQuery); + const item = await PermissionsService.readPermission(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) @@ -67,9 +74,9 @@ router.patch( router.delete( '/:pk', - useCollection('directus_permissions'), asyncHandler(async (req, res) => { await PermissionsService.deletePermission(Number(req.params.pk), { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, diff --git a/src/routes/presets.ts b/src/routes/presets.ts index 0a319aa99d..4051353d72 100644 --- a/src/routes/presets.ts +++ b/src/routes/presets.ts @@ -6,11 +6,13 @@ import useCollection from '../middleware/use-collection'; const router = express.Router(); +router.use(useCollection('directus_presets')); + router.post( '/', - useCollection('directus_presets'), asyncHandler(async (req, res) => { const primaryKey = await CollectionPresetsService.createCollectionPreset(req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, @@ -18,7 +20,8 @@ router.post( const record = await CollectionPresetsService.readCollectionPreset( primaryKey, - req.sanitizedQuery + req.sanitizedQuery, + { role: req.role } ); return res.json({ data: record || null }); }) @@ -26,22 +29,23 @@ router.post( router.get( '/', - useCollection('directus_presets'), sanitizeQuery, asyncHandler(async (req, res) => { - // const records = await CollectionPresetsService.readCollectionPresets(req.sanitizedQuery); - // return res.json({ data: records || null }); + const records = await CollectionPresetsService.readCollectionPresets(req.sanitizedQuery, { + role: req.role, + }); + return res.json({ data: records || null }); }) ); router.get( '/:pk', - useCollection('directus_presets'), sanitizeQuery, asyncHandler(async (req, res) => { const record = await CollectionPresetsService.readCollectionPreset( req.params.pk, - req.sanitizedQuery + req.sanitizedQuery, + { role: req.role } ); return res.json({ data: record || null }); }) @@ -49,13 +53,13 @@ router.get( router.patch( '/:pk', - useCollection('directus_presets'), sanitizeQuery, asyncHandler(async (req, res) => { const primaryKey = await CollectionPresetsService.updateCollectionPreset( req.params.pk, req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, @@ -64,7 +68,8 @@ router.patch( const record = await CollectionPresetsService.readCollectionPreset( primaryKey, - req.sanitizedQuery + req.sanitizedQuery, + { role: req.role } ); return res.json({ data: record || null }); }) @@ -72,9 +77,9 @@ router.patch( router.delete( '/:pk', - useCollection('directus_presets'), asyncHandler(async (req, res) => { await CollectionPresetsService.deleteCollectionPreset(req.params.pk, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, diff --git a/src/routes/relations.ts b/src/routes/relations.ts index fe91168eef..aef2541b25 100644 --- a/src/routes/relations.ts +++ b/src/routes/relations.ts @@ -6,61 +6,69 @@ import useCollection from '../middleware/use-collection'; const router = express.Router(); +router.use(useCollection('directus_relations')); + router.post( '/', - useCollection('directus_relations'), sanitizeQuery, asyncHandler(async (req, res) => { const primaryKey = await RelationsService.createRelation(req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const item = await RelationsService.readRelation(primaryKey, req.sanitizedQuery); + const item = await RelationsService.readRelation(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) ); router.get( '/', - useCollection('directus_relations'), sanitizeQuery, asyncHandler(async (req, res) => { - // const records = await RelationsService.readRelations(req.sanitizedQuery); - // return res.json({ data: records || null }); + const records = await RelationsService.readRelations(req.sanitizedQuery, { + role: req.role, + }); + return res.json({ data: records || null }); }) ); router.get( '/:pk', - useCollection('directus_relations'), sanitizeQuery, asyncHandler(async (req, res) => { - const record = await RelationsService.readRelation(req.params.pk, req.sanitizedQuery); + const record = await RelationsService.readRelation(req.params.pk, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: record || null }); }) ); router.patch( '/:pk', - useCollection('directus_relations'), sanitizeQuery, asyncHandler(async (req, res) => { const primaryKey = await RelationsService.updateRelation(req.params.pk, req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const item = await RelationsService.readRelation(primaryKey, req.sanitizedQuery); + const item = await RelationsService.readRelation(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) ); router.delete( '/:pk', - useCollection('directus_relations'), asyncHandler(async (req, res) => { await RelationsService.deleteRelation(Number(req.params.pk), { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, diff --git a/src/routes/revisions.ts b/src/routes/revisions.ts index ca72f46883..9e878e29b8 100644 --- a/src/routes/revisions.ts +++ b/src/routes/revisions.ts @@ -6,22 +6,26 @@ import useCollection from '../middleware/use-collection'; const router = express.Router(); +router.use(useCollection('directus_revisions')); + router.get( '/', - useCollection('directus_revisions'), sanitizeQuery, asyncHandler(async (req, res) => { - // const records = await RevisionsService.readRevisions(req.sanitizedQuery); - // return res.json({ data: records || null }); + const records = await RevisionsService.readRevisions(req.sanitizedQuery, { + role: req.role, + }); + return res.json({ data: records || null }); }) ); router.get( '/:pk', - useCollection('directus_revisions'), sanitizeQuery, asyncHandler(async (req, res) => { - const record = await RevisionsService.readRevision(req.params.pk, req.sanitizedQuery); + const record = await RevisionsService.readRevision(req.params.pk, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: record || null }); }) ); diff --git a/src/routes/roles.ts b/src/routes/roles.ts index 272b8d41d7..585189c0f8 100644 --- a/src/routes/roles.ts +++ b/src/routes/roles.ts @@ -6,61 +6,67 @@ import useCollection from '../middleware/use-collection'; const router = express.Router(); +router.use(useCollection('directus_roles')); + router.post( '/', - useCollection('directus_roles'), sanitizeQuery, asyncHandler(async (req, res) => { const primaryKey = await RolesService.createRole(req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const item = await RolesService.readRole(primaryKey, req.sanitizedQuery); + const item = await RolesService.readRole(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) ); router.get( '/', - useCollection('directus_roles'), sanitizeQuery, asyncHandler(async (req, res) => { - // const records = await RolesService.readRoles(req.sanitizedQuery); - // return res.json({ data: records || null }); + const records = await RolesService.readRoles(req.sanitizedQuery, { role: req.role }); + return res.json({ data: records || null }); }) ); router.get( '/:pk', - useCollection('directus_roles'), sanitizeQuery, asyncHandler(async (req, res) => { - const record = await RolesService.readRole(req.params.pk, req.sanitizedQuery); + const record = await RolesService.readRole(req.params.pk, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: record || null }); }) ); router.patch( '/:pk', - useCollection('directus_roles'), sanitizeQuery, asyncHandler(async (req, res) => { const primaryKey = await RolesService.updateRole(req.params.pk, req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const item = await RolesService.readRole(primaryKey, req.sanitizedQuery); + const item = await RolesService.readRole(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) ); router.delete( '/:pk', - useCollection('directus_roles'), asyncHandler(async (req, res) => { await RolesService.deleteRole(req.params.pk, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, diff --git a/src/routes/settings.ts b/src/routes/settings.ts index f5b84ff546..308475edb7 100644 --- a/src/routes/settings.ts +++ b/src/routes/settings.ts @@ -11,8 +11,8 @@ router.get( useCollection('directus_settings'), sanitizeQuery, asyncHandler(async (req, res) => { - const records = await SettingsService.readSettings(req.sanitizedQuery); - // return res.json({ data: records || null }); + const records = await SettingsService.readSettings(req.sanitizedQuery, { role: req.role }); + return res.json({ data: records || null }); }) ); @@ -22,14 +22,15 @@ router.patch( sanitizeQuery, asyncHandler(async (req, res) => { await SettingsService.updateSettings(req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - // const record = await SettingsService.readSettings(req.sanitizedQuery); + const record = await SettingsService.readSettings(req.sanitizedQuery, { role: req.role }); - // return res.json({ data: record || null }); + return res.json({ data: record || null }); }) ); diff --git a/src/routes/users.ts b/src/routes/users.ts index 1839235072..7a4da26ff8 100644 --- a/src/routes/users.ts +++ b/src/routes/users.ts @@ -8,58 +8,60 @@ import useCollection from '../middleware/use-collection'; const router = express.Router(); +router.use(useCollection('directus_users')); + router.post( '/', - useCollection('directus_users'), sanitizeQuery, asyncHandler(async (req, res) => { const primaryKey = await UsersService.createUser(req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const item = await UsersService.readUser(primaryKey, req.sanitizedQuery); + const item = await UsersService.readUser(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) ); router.get( '/', - useCollection('directus_users'), sanitizeQuery, asyncHandler(async (req, res) => { - // const item = await UsersService.readUsers(req.sanitizedQuery); - // return res.json({ data: item || null }); + const item = await UsersService.readUsers(req.sanitizedQuery, { role: req.role }); + return res.json({ data: item || null }); }) ); router.get( '/me', - useCollection('directus_users'), sanitizeQuery, asyncHandler(async (req, res) => { if (!req.user) { throw new InvalidCredentialsException(); } - const item = await UsersService.readUser(req.user, req.sanitizedQuery); + const item = await UsersService.readUser(req.user, req.sanitizedQuery, { role: req.role }); return res.json({ data: item || null }); }) ); router.get( '/:pk', - useCollection('directus_users'), sanitizeQuery, asyncHandler(async (req, res) => { - const items = await UsersService.readUser(req.params.pk, req.sanitizedQuery); + const items = await UsersService.readUser(req.params.pk, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: items || null }); }) ); router.patch( '/me', - useCollection('directus_users'), sanitizeQuery, asyncHandler(async (req, res) => { if (!req.user) { @@ -67,36 +69,41 @@ router.patch( } const primaryKey = await UsersService.updateUser(req.user, req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const item = await UsersService.readUser(primaryKey, req.sanitizedQuery); + const item = await UsersService.readUser(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) ); router.patch( '/:pk', - useCollection('directus_users'), sanitizeQuery, asyncHandler(async (req, res) => { const primaryKey = await UsersService.updateUser(req.params.pk, req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const item = await UsersService.readUser(primaryKey, req.sanitizedQuery); + const item = await UsersService.readUser(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) ); router.delete( '/:pk', - useCollection('directus_users'), asyncHandler(async (req, res) => { await UsersService.deleteUser(req.params.pk, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, @@ -113,11 +120,11 @@ const inviteSchema = Joi.object({ router.post( '/invite', - useCollection('directus_users'), asyncHandler(async (req, res) => { const { error } = inviteSchema.validate(req.body); if (error) throw new InvalidPayloadException(error.message); await UsersService.inviteUser(req.body.email, req.body.role, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, @@ -133,7 +140,6 @@ const acceptInviteSchema = Joi.object({ router.post( '/invite/accept', - useCollection('directus_users'), asyncHandler(async (req, res) => { const { error } = acceptInviteSchema.validate(req.body); if (error) throw new InvalidPayloadException(error.message); diff --git a/src/routes/webhooks.ts b/src/routes/webhooks.ts index 058ab9cd8e..c6e86520a9 100644 --- a/src/routes/webhooks.ts +++ b/src/routes/webhooks.ts @@ -6,17 +6,21 @@ import useCollection from '../middleware/use-collection'; const router = express.Router(); +router.use(useCollection('directus_webhooks')); + router.post( '/', - useCollection('directus_webhooks'), asyncHandler(async (req, res) => { const primaryKey = await WebhooksService.createWebhook(req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const item = await WebhooksService.readWebhook(primaryKey, req.sanitizedQuery); + const item = await WebhooksService.readWebhook(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) @@ -24,43 +28,45 @@ router.post( router.get( '/', - useCollection('directus_webhooks'), sanitizeQuery, asyncHandler(async (req, res) => { - // const records = await WebhooksService.readWebhooks(req.sanitizedQuery); - // return res.json({ data: records || null }); + const records = await WebhooksService.readWebhooks(req.sanitizedQuery, { role: req.role }); + return res.json({ data: records || null }); }) ); router.get( '/:pk', - useCollection('directus_webhooks'), sanitizeQuery, asyncHandler(async (req, res) => { - const record = await WebhooksService.readWebhook(req.params.pk, req.sanitizedQuery); + const record = await WebhooksService.readWebhook(req.params.pk, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: record || null }); }) ); router.patch( '/:pk', - useCollection('directus_webhooks'), asyncHandler(async (req, res) => { const primaryKey = await WebhooksService.updateWebhook(req.params.pk, req.body, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, }); - const item = await WebhooksService.readWebhook(primaryKey, req.sanitizedQuery); + const item = await WebhooksService.readWebhook(primaryKey, req.sanitizedQuery, { + role: req.role, + }); return res.json({ data: item || null }); }) ); router.delete( '/:pk', - useCollection('directus_webhooks'), asyncHandler(async (req, res) => { await WebhooksService.deleteWebhook(req.params.pk, { + role: req.role, ip: req.ip, userAgent: req.get('user-agent'), user: req.user, diff --git a/src/services/activity.ts b/src/services/activity.ts index f601468b26..28b875066d 100644 --- a/src/services/activity.ts +++ b/src/services/activity.ts @@ -16,12 +16,16 @@ export const createActivity = async (data: Record) => { return await ItemsService.createItem('directus_activity', data); }; -export const readActivities = async (query?: Query) => { - // return await ItemsService.readItems('directus_activity', query); +export const readActivities = async (query?: Query, accountability?: Accountability) => { + return await ItemsService.readItems('directus_activity', query, accountability); }; -export const readActivity = async (pk: string | number, query?: Query) => { - return await ItemsService.readItem('directus_activity', pk, query); +export const readActivity = async ( + pk: string | number, + query?: Query, + accountability?: Accountability +) => { + return await ItemsService.readItem('directus_activity', pk, query, accountability); }; export const updateActivity = async ( diff --git a/src/services/collections.ts b/src/services/collections.ts index 30ebf4410b..19a255305d 100644 --- a/src/services/collections.ts +++ b/src/services/collections.ts @@ -70,34 +70,43 @@ export const create = async (payload: any, accountability: Accountability) => { return await ItemsService.readItem('directus_collections', primaryKey); }; -export const readAll = async (query?: Query) => { +export const readAll = async (query?: Query, accountability?: Accountability) => { const [tables, collections] = await Promise.all([ schemaInspector.tableInfo(), - // ItemsService.readItems('directus_collections', query), + ItemsService.readItems('directus_collections', query, accountability), ]); - // const data = tables.map((table) => { - // const collectionInfo = collections.find((collection) => { - // return collection.collection === table.name; - // }); + const data = tables.map((table) => { + const collectionInfo = collections.find((collection) => { + return collection.collection === table.name; + }); - // return { - // collection: table.name, - // note: table.comment, - // hidden: collectionInfo?.hidden || false, - // single: collectionInfo?.single || false, - // icon: collectionInfo?.icon || null, - // translation: collectionInfo?.translation || null, - // }; - // }); + return { + collection: table.name, + note: table.comment, + hidden: collectionInfo?.hidden || false, + single: collectionInfo?.single || false, + icon: collectionInfo?.icon || null, + translation: collectionInfo?.translation || null, + }; + }); - // return data; + return data; }; -export const readOne = async (collection: string, query?: Query) => { +export const readOne = async ( + collection: string, + query?: Query, + accountability?: Accountability +) => { const [table, collectionInfo] = await Promise.all([ schemaInspector.tableInfo(collection), - ItemsService.readItem('directus_collections', collection, query), + ItemsService.readItem( + 'directus_collections', + collection, + query, + accountability + ), ]); return { diff --git a/src/services/fields.ts b/src/services/fields.ts index ce0f0f784f..df39365979 100644 --- a/src/services/fields.ts +++ b/src/services/fields.ts @@ -13,6 +13,11 @@ export const fieldsInCollection = async (collection: string) => { return uniq([...fields.map(({ field }) => field), ...columns.map(({ column }) => column)]); }; +/** + * @TODO + * update read to use ItemsService instead of direct to db + */ + export const readAll = async (collection?: string) => { const fieldsQuery = database.select('*').from('directus_fields'); diff --git a/src/services/files.ts b/src/services/files.ts index e65c1f209e..9062c46dd7 100644 --- a/src/services/files.ts +++ b/src/services/files.ts @@ -56,12 +56,16 @@ export const createFile = async ( return await ItemsService.createItem('directus_files', payload, accountability); }; -export const readFiles = async (query: Query) => { - // return await ItemsService.readItems('directus_files', query); +export const readFiles = async (query: Query, accountability?: Accountability) => { + return await ItemsService.readItems('directus_files', query, accountability); }; -export const readFile = async (pk: string | number, query: Query) => { - return await ItemsService.readItem('directus_files', pk, query); +export const readFile = async ( + pk: string | number, + query: Query, + accountability?: Accountability +) => { + return await ItemsService.readItem('directus_files', pk, query, accountability); }; export const updateFile = async ( diff --git a/src/services/folders.ts b/src/services/folders.ts index b3f9a9bd6a..66887d0432 100644 --- a/src/services/folders.ts +++ b/src/services/folders.ts @@ -8,12 +8,12 @@ export const createFolder = async ( return (await ItemsService.createItem('directus_folders', data, accountability)) as string; }; -export const readFolders = async (query: Query) => { - // return await ItemsService.readItems('directus_folders', query); +export const readFolders = async (query: Query, accountability?: Accountability) => { + return await ItemsService.readItems('directus_folders', query, accountability); }; -export const readFolder = async (pk: string, query: Query) => { - return await ItemsService.readItem('directus_folders', pk, query); +export const readFolder = async (pk: string, query: Query, accountability?: Accountability) => { + return await ItemsService.readItem('directus_folders', pk, query, accountability); }; export const updateFolder = async ( diff --git a/src/services/items.ts b/src/services/items.ts index 9ee1f6f82c..efc1e1e0f4 100644 --- a/src/services/items.ts +++ b/src/services/items.ts @@ -1,10 +1,11 @@ import database, { schemaInspector } from '../database'; import { Query } from '../types/query'; import runAST from '../database/run-ast'; -import getAST from '../utils/get-ast-from-query'; -import * as PayloadService from './payload'; +import getASTFromQuery from '../utils/get-ast-from-query'; import { Accountability, AST } from '../types'; +import * as PayloadService from './payload'; +import * as PermissionsService from './permissions'; import * as ActivityService from './activity'; import * as RevisionsService from './revisions'; @@ -82,8 +83,15 @@ export const createItem = async ( export const readItems = async >( collection: string, - ast: AST + query: Query, + accountability?: Accountability ): Promise => { + let ast = await getASTFromQuery(collection, query, accountability?.role); + + if (accountability) { + ast = await PermissionsService.processAST(ast, accountability.role); + } + const records = await runAST(ast); return await PayloadService.processValues('read', collection, records); }; @@ -91,7 +99,8 @@ export const readItems = async >( export const readItem = async ( collection: string, pk: number | string, - query: Query = {} + query: Query = {}, + accountability?: Accountability ): Promise => { const primaryKeyField = await schemaInspector.primary(collection); @@ -105,10 +114,14 @@ export const readItem = async ( }, }; - // const ast = await getAST(collection, query); - // const records = await runAST(ast); - // return await PayloadService.processValues('read', collection, records[0]); - return; + let ast = await getASTFromQuery(collection, query, accountability?.role); + + if (accountability) { + ast = await PermissionsService.processAST(ast, accountability.role); + } + + const records = await runAST(ast); + return await PayloadService.processValues('read', collection, records[0]); }; export const updateItem = async ( @@ -172,10 +185,14 @@ export const deleteItem = async ( .where({ [primaryKeyField]: pk }); }; -export const readSingleton = async (collection: string, ast: AST) => { - ast.query.limit = 1; +export const readSingleton = async ( + collection: string, + query: Query, + accountability?: Accountability +) => { + query.limit = 1; - const records = await readItems(collection, ast); + const records = await readItems(collection, query, accountability); const record = records[0]; if (!record) { diff --git a/src/services/permissions.ts b/src/services/permissions.ts index 1982fd6b2f..37f8571fd9 100644 --- a/src/services/permissions.ts +++ b/src/services/permissions.ts @@ -1,13 +1,4 @@ -import { - Accountability, - AST, - NestedCollectionAST, - FieldAST, - Operation, - Query, - Permission, - Relation, -} from '../types'; +import { Accountability, AST, NestedCollectionAST, FieldAST, Query, Permission } from '../types'; import * as ItemsService from './items'; import database from '../database'; import { ForbiddenException } from '../exceptions'; @@ -20,12 +11,12 @@ export const createPermission = async ( return (await ItemsService.createItem('directus_permissions', data, accountability)) as number; }; -export const readPermissions = async (query: Query) => { - // return await ItemsService.readItems('directus_permissions', query); +export const readPermissions = async (query: Query, accountability?: Accountability) => { + return await ItemsService.readItems('directus_permissions', query, accountability); }; -export const readPermission = async (pk: number, query: Query) => { - return await ItemsService.readItem('directus_permissions', pk, query); +export const readPermission = async (pk: number, query: Query, accountability?: Accountability) => { + return await ItemsService.readItem('directus_permissions', pk, query, accountability); }; export const updatePermission = async ( @@ -45,41 +36,17 @@ export const deletePermission = async (pk: number, accountability: Accountabilit await ItemsService.deleteItem('directus_permissions', pk, accountability); }; -export const authorize = async (operation: Operation, collection: string, role?: string) => { - const query: Query = { - filter: { - collection: { - _eq: collection, - }, - operation: { - _eq: operation, - }, - }, - limit: 1, - }; - - if (role) { - query.filter.role = { - _eq: role, - }; - } - - // const records = await ItemsService.readItems('directus_permissions', query); - - // return records[0]; -}; - -export const processAST = async (role: string | null, ast: AST): Promise => { +export const processAST = async (ast: AST, role: string | null): Promise => { const collectionsRequested = getCollectionsFromAST(ast); const permissionsForCollections = await database .select('*') .from('directus_permissions') + .where({ operation: 'read', role }) .whereIn( 'collection', collectionsRequested.map(({ collection }) => collection) - ) - .andWhere('role', role); + ); // If the permissions don't match the collections, you don't have permission to read all of them const uniqueCollectionsRequestedCount = uniq( diff --git a/src/services/presets.ts b/src/services/presets.ts index 8012bec5c8..86a7bbff86 100644 --- a/src/services/presets.ts +++ b/src/services/presets.ts @@ -10,12 +10,16 @@ export const createCollectionPreset = async ( return await ItemsService.createItem('directus_presets', data, accountability); }; -export const readCollectionPresets = async (query: Query) => { - // return await ItemsService.readItems('directus_presets', query); +export const readCollectionPresets = async (query: Query, accountability?: Accountability) => { + return await ItemsService.readItems('directus_presets', query, accountability); }; -export const readCollectionPreset = async (pk: string | number, query: Query) => { - return await ItemsService.readItem('directus_presets', pk, query); +export const readCollectionPreset = async ( + pk: string | number, + query: Query, + accountability?: Accountability +) => { + return await ItemsService.readItem('directus_presets', pk, query, accountability); }; export const updateCollectionPreset = async ( diff --git a/src/services/relations.ts b/src/services/relations.ts index 8ff4acb432..1a9c0dbfc5 100644 --- a/src/services/relations.ts +++ b/src/services/relations.ts @@ -5,12 +5,16 @@ export const createRelation = async (data: Record, accountability: return await ItemsService.createItem('directus_relations', data, accountability); }; -export const readRelations = async (query: Query) => { - // return await ItemsService.readItems('directus_relations', query); +export const readRelations = async (query: Query, accountability?: Accountability) => { + return await ItemsService.readItems('directus_relations', query, accountability); }; -export const readRelation = async (pk: string | number, query: Query) => { - return await ItemsService.readItem('directus_relations', pk, query); +export const readRelation = async ( + pk: string | number, + query: Query, + accountability?: Accountability +) => { + return await ItemsService.readItem('directus_relations', pk, query, accountability); }; export const updateRelation = async ( diff --git a/src/services/revisions.ts b/src/services/revisions.ts index 9c425ae231..0d6a7b4538 100644 --- a/src/services/revisions.ts +++ b/src/services/revisions.ts @@ -1,14 +1,18 @@ -import { Query } from '../types/query'; import * as ItemsService from './items'; +import { Accountability, Query } from '../types'; export const createRevision = async (data: Record) => { return await ItemsService.createItem('directus_revisions', data); }; -export const readRevisions = async (query: Query) => { - // return await ItemsService.readItems('directus_revisions', query); +export const readRevisions = async (query: Query, accountability?: Accountability) => { + return await ItemsService.readItems('directus_revisions', query, accountability); }; -export const readRevision = async (pk: string | number, query: Query) => { - return await ItemsService.readItem('directus_revisions', pk, query); +export const readRevision = async ( + pk: string | number, + query: Query, + accountability?: Accountability +) => { + return await ItemsService.readItem('directus_revisions', pk, query, accountability); }; diff --git a/src/services/roles.ts b/src/services/roles.ts index cc357c8dd2..5558421424 100644 --- a/src/services/roles.ts +++ b/src/services/roles.ts @@ -5,12 +5,16 @@ export const createRole = async (data: Record, accountability: Acco return await ItemsService.createItem('directus_roles', data, accountability); }; -export const readRoles = async (query: Query) => { - // return await ItemsService.readItems('directus_roles', query); +export const readRoles = async (query: Query, accountability?: Accountability) => { + return await ItemsService.readItems('directus_roles', query, accountability); }; -export const readRole = async (pk: string | number, query: Query) => { - return await ItemsService.readItem('directus_roles', pk, query); +export const readRole = async ( + pk: string | number, + query: Query, + accountability?: Accountability +) => { + return await ItemsService.readItem('directus_roles', pk, query, accountability); }; export const updateRole = async ( diff --git a/src/services/settings.ts b/src/services/settings.ts index 06198767cf..decb16dffa 100644 --- a/src/services/settings.ts +++ b/src/services/settings.ts @@ -2,8 +2,8 @@ import { Query } from '../types/query'; import * as ItemsService from './items'; import { Accountability } from '../types'; -export const readSettings = async (query: Query) => { - // return await ItemsService.readSingleton('directus_settings', query); +export const readSettings = async (query: Query, accountability?: Accountability) => { + return await ItemsService.readSingleton('directus_settings', query, accountability); }; export const updateSettings = async (data: Record, accountability: Accountability) => { diff --git a/src/services/users.ts b/src/services/users.ts index ddce886f5d..d504ff7c9b 100644 --- a/src/services/users.ts +++ b/src/services/users.ts @@ -10,12 +10,16 @@ export const createUser = async (data: Record, accountability: Acco return await ItemsService.createItem('directus_users', data, accountability); }; -export const readUsers = async (query?: Query) => { - // return await ItemsService.readItems('directus_users', query); +export const readUsers = async (query?: Query, accountability?: Accountability) => { + return await ItemsService.readItems('directus_users', query, accountability); }; -export const readUser = async (pk: string | number, query?: Query) => { - return await ItemsService.readItem('directus_users', pk, query); +export const readUser = async ( + pk: string | number, + query?: Query, + accountability?: Accountability +) => { + return await ItemsService.readItem('directus_users', pk, query, accountability); }; export const updateUser = async ( diff --git a/src/services/webhooks.ts b/src/services/webhooks.ts index c7e9d80b29..5e7476b0ed 100644 --- a/src/services/webhooks.ts +++ b/src/services/webhooks.ts @@ -5,12 +5,16 @@ export const createWebhook = async (data: Record, accountability: A return await ItemsService.createItem('directus_webhooks', data, accountability); }; -export const readWebhooks = async (query: Query) => { - // return await ItemsService.readItems('directus_webhooks', query); +export const readWebhooks = async (query: Query, accountability?: Accountability) => { + return await ItemsService.readItems('directus_webhooks', query, accountability); }; -export const readWebhook = async (pk: string | number, query: Query) => { - return await ItemsService.readItem('directus_webhooks', pk, query); +export const readWebhook = async ( + pk: string | number, + query: Query, + accountability?: Accountability +) => { + return await ItemsService.readItem('directus_webhooks', pk, query, accountability); }; export const updateWebhook = async ( diff --git a/src/types/accountability.ts b/src/types/accountability.ts index 8bdebbea82..e30a3efa6b 100644 --- a/src/types/accountability.ts +++ b/src/types/accountability.ts @@ -1,7 +1,8 @@ export type Accountability = { + role: string; + user?: string; ip?: string; userAgent?: string; - user?: string; parent?: number; }; diff --git a/src/utils/get-ast-from-query.ts b/src/utils/get-ast-from-query.ts index eec6fcb6b1..644d94f64d 100644 --- a/src/utils/get-ast-from-query.ts +++ b/src/utils/get-ast-from-query.ts @@ -4,23 +4,27 @@ import { Relation } from '../types/relation'; import { AST, NestedCollectionAST, FieldAST, Query } from '../types'; -import database, { schemaInspector } from '../database'; +import database from '../database'; export default async function getASTFromQuery( - role: string | null, collection: string, - query: Query + query: Query, + role?: string | null ): Promise { /** * we might not need al this info at all times, but it's easier to fetch it all once, than trying to fetch it for every * requested field. @todo look into utilizing graphql/dataloader for this purpose */ - const permissions = await database - .select<{ collection: string; fields: string }[]>('collection', 'fields') - .from('directus_permissions') - .where({ role, operation: 'read' }); const relations = await database.select('*').from('directus_relations'); + const permissions = + role !== undefined + ? await database + .select<{ collection: string; fields: string }[]>('collection', 'fields') + .from('directus_permissions') + .where({ role, operation: 'read' }) + : null; + const ast: AST = { type: 'collection', name: collection, @@ -39,8 +43,10 @@ export default async function getASTFromQuery( function convertWildcards(parentCollection: string, fields: string[]) { const allowedFields = permissions - .find((permission) => parentCollection === permission.collection) - ?.fields?.split(','); + ? permissions + .find((permission) => parentCollection === permission.collection) + ?.fields?.split(',') + : ['*']; if (!allowedFields || allowedFields.length === 0) return [];