mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Auto gen UUID field on create
This commit is contained in:
34
package-lock.json
generated
34
package-lock.json
generated
@@ -22,6 +22,13 @@
|
||||
"tunnel": "0.0.6",
|
||||
"uuid": "^3.2.1",
|
||||
"xml2js": "^0.4.19"
|
||||
},
|
||||
"dependencies": {
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@azure/ms-rest-nodeauth": {
|
||||
@@ -316,6 +323,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/uuid": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.0.0.tgz",
|
||||
"integrity": "sha512-xSQfNcvOiE5f9dyd4Kzxbof1aTrLobL278pGLKOZI6esGfZ7ts9Ka16CzIN6Y8hFHE1C7jIBZokULhK1bOgjRw==",
|
||||
"dev": true
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
@@ -362,6 +375,11 @@
|
||||
"version": "8.10.61",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.61.tgz",
|
||||
"integrity": "sha512-l+zSbvT8TPRaCxL1l9cwHCb0tSqGAGcjPJFItGGYat5oCTiq1uQQKYg5m7AF1mgnEBzFXGLJ2LRmNjtreRX76Q=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4623,6 +4641,11 @@
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4645,6 +4668,11 @@
|
||||
"version": "6.9.4",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz",
|
||||
"integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5737,9 +5765,9 @@
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz",
|
||||
"integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q=="
|
||||
},
|
||||
"v8-compile-cache": {
|
||||
"version": "2.1.1",
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
"@types/lodash": "^4.14.156",
|
||||
"@types/nodemailer": "^6.4.0",
|
||||
"@types/pino": "^6.3.0",
|
||||
"@types/uuid": "^8.0.0",
|
||||
"copyfiles": "^2.3.0",
|
||||
"eslint": "^7.3.1",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
@@ -85,6 +86,7 @@
|
||||
"pg": "^8.2.1",
|
||||
"pino": "^6.3.2",
|
||||
"sqlite3": "^4.2.0",
|
||||
"ts-node-dev": "^1.0.0-pre.49"
|
||||
"ts-node-dev": "^1.0.0-pre.49",
|
||||
"uuid": "^8.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,26 +17,17 @@ async function getCollections(keys: string[]) {
|
||||
return keys.map((key) => records.find((collection) => collection.collection === key));
|
||||
}
|
||||
|
||||
async function getFields(keys: { collection: string; field: string }[]) {
|
||||
const records = await database
|
||||
.select('*')
|
||||
.from('directus_fields')
|
||||
.whereIn(
|
||||
['collection', 'field'],
|
||||
keys.map((key) => [key.collection, key.field])
|
||||
);
|
||||
|
||||
return keys.map<FieldInfo>((key) =>
|
||||
records.find((record) => record.collection === key.collection && record.field === key.field)
|
||||
);
|
||||
}
|
||||
|
||||
export default function createSystemLoaders() {
|
||||
return {
|
||||
collections: new DataLoader(getCollections),
|
||||
fields: new DataLoader(getFields, {
|
||||
cacheKeyFn: (key: { collection: string; field: string }) =>
|
||||
key.collection + '__' + key.field,
|
||||
}),
|
||||
fieldsByCollection: new DataLoader<string, FieldInfo[]>((collections: string[]) =>
|
||||
database
|
||||
.select('*')
|
||||
.from('directus_fields')
|
||||
.whereIn('collection', collections)
|
||||
.then((rows) =>
|
||||
collections.map((collection) => rows.filter((x) => x.collection === collection))
|
||||
)
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ import isJWT from '../utils/is-jwt';
|
||||
import database from '../database';
|
||||
import asyncHandler from 'express-async-handler';
|
||||
|
||||
/**
|
||||
* Verify the passed JWT and assign the user ID and role to `req`
|
||||
*/
|
||||
const authenticate: RequestHandler = asyncHandler(async (req, res, next) => {
|
||||
if (!req.token) return next();
|
||||
|
||||
|
||||
@@ -7,34 +7,24 @@ import { RequestHandler } from 'express';
|
||||
import asyncHandler from 'express-async-handler';
|
||||
import { FieldInfo } from '../types/field';
|
||||
import bcrypt from 'bcrypt';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
type Operation = 'create' | 'update';
|
||||
|
||||
/**
|
||||
* @TODO
|
||||
*
|
||||
* This needs a bit of extra thinking.
|
||||
* - There's a difference between update / create payload processing
|
||||
* - Some processing types need the whole payload (slug)
|
||||
* - What happens for fields that aren't in the payload but need to be set on create?
|
||||
* Move this out of the middleware into a service
|
||||
*/
|
||||
|
||||
const processPayload = (operation: Operation) => {
|
||||
const middleware: RequestHandler = asyncHandler(async (req, res, next) => {
|
||||
// Get the fields that have a special operation associated with them
|
||||
const fieldsInPayload = Object.keys(req.body);
|
||||
const fieldsInCollection = await req.loaders.fieldsByCollection.load(req.collection);
|
||||
|
||||
const fieldInfoForFields = await req.loaders.fields.loadMany(
|
||||
fieldsInPayload.map((field) => ({
|
||||
collection: req.collection,
|
||||
field: field,
|
||||
}))
|
||||
);
|
||||
|
||||
const specialFields = fieldInfoForFields.filter((field) => {
|
||||
const specialFields = fieldsInCollection.filter((field) => {
|
||||
if (field instanceof Error) return false;
|
||||
return field.special !== null;
|
||||
}) as FieldInfo[];
|
||||
});
|
||||
|
||||
for (const field of specialFields) {
|
||||
req.body[field.field] = await processField(req.collection, field, req.body, operation);
|
||||
@@ -54,12 +44,20 @@ async function processField(
|
||||
) {
|
||||
switch (field.special) {
|
||||
case 'hash':
|
||||
return await hash(payload[field.field]);
|
||||
return await genHash(payload[field.field]);
|
||||
case 'uuid':
|
||||
return await genUUID(operation);
|
||||
}
|
||||
}
|
||||
|
||||
async function hash(value: string | number) {
|
||||
async function genHash(value: string | number) {
|
||||
return await bcrypt.hash(value, Number(process.env.SALT_ROUNDS));
|
||||
}
|
||||
|
||||
async function genUUID(operation: Operation) {
|
||||
if (operation === 'create') {
|
||||
return uuidv4();
|
||||
}
|
||||
}
|
||||
|
||||
export default processPayload;
|
||||
|
||||
Reference in New Issue
Block a user