mirror of
https://github.com/directus/directus.git
synced 2026-02-03 12:45:08 -05:00
Various fixes to address issues in app
This commit is contained in:
@@ -3,133 +3,6 @@ import { uniq } from 'lodash';
|
||||
import database from './index';
|
||||
import { Query } from '../types/query';
|
||||
|
||||
// const testAST: AST = {
|
||||
// type: 'collection',
|
||||
// name: 'articles',
|
||||
// query: {},
|
||||
// children: [
|
||||
// {
|
||||
// type: 'field',
|
||||
// name: 'id'
|
||||
// },
|
||||
// {
|
||||
// type: 'field',
|
||||
// name: 'title',
|
||||
// },
|
||||
// {
|
||||
// type: 'collection',
|
||||
// name: 'authors',
|
||||
// fieldKey: 'author_id',
|
||||
// parentKey: 'id',
|
||||
// relation: {
|
||||
// id: 2,
|
||||
// collection_many: 'articles',
|
||||
// field_many: 'author_id',
|
||||
// collection_one: 'authors',
|
||||
// primary_one: 'id',
|
||||
// field_one: null
|
||||
// },
|
||||
// query: {},
|
||||
// children: [
|
||||
// {
|
||||
// type: 'field',
|
||||
// name: 'id'
|
||||
// },
|
||||
// {
|
||||
// type: 'field',
|
||||
// name: 'name'
|
||||
// },
|
||||
// {
|
||||
// type: 'collection',
|
||||
// name: 'movies',
|
||||
// fieldKey: 'movies',
|
||||
// parentKey: 'id',
|
||||
// relation: {
|
||||
// id: 3,
|
||||
// collection_many: 'movies',
|
||||
// field_many: 'author_id',
|
||||
// collection_one: 'authors',
|
||||
// primary_one: 'id',
|
||||
// field_one: 'movies'
|
||||
// },
|
||||
// query: {},
|
||||
// children: [
|
||||
// {
|
||||
// type: 'field',
|
||||
// name: 'id',
|
||||
// },
|
||||
// {
|
||||
// type: 'field',
|
||||
// name: 'title'
|
||||
// },
|
||||
// {
|
||||
// type: 'collection',
|
||||
// name: 'authors',
|
||||
// fieldKey: 'author_id',
|
||||
// parentKey: 'id',
|
||||
// relation: {
|
||||
// id: 4,
|
||||
// collection_many: 'movies',
|
||||
// field_many: 'author_id',
|
||||
// collection_one: 'authors',
|
||||
// primary_one: 'id',
|
||||
// field_one: 'movies',
|
||||
// },
|
||||
// query: {},
|
||||
// children: [
|
||||
// {
|
||||
// type: 'field',
|
||||
// name: 'id',
|
||||
// },
|
||||
// {
|
||||
// type: 'field',
|
||||
// name: 'name',
|
||||
// },
|
||||
// {
|
||||
// type: 'collection',
|
||||
// name: 'movies',
|
||||
// fieldKey: 'movies',
|
||||
// parentKey: 'id',
|
||||
// relation: {
|
||||
// id: 6,
|
||||
// collection_many: 'movies',
|
||||
// field_many: 'author_id',
|
||||
// collection_one: 'authors',
|
||||
// primary_one: 'id',
|
||||
// field_one: 'movies'
|
||||
// },
|
||||
// query: {
|
||||
// sort: [
|
||||
// {
|
||||
// column: 'title',
|
||||
// order: 'asc'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// children: [
|
||||
// {
|
||||
// type: 'field',
|
||||
// name: 'id'
|
||||
// },
|
||||
// {
|
||||
// type: 'field',
|
||||
// name: 'title'
|
||||
// },
|
||||
// {
|
||||
// type: 'field',
|
||||
// name: 'author_id'
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
|
||||
export default async function runAST(ast: AST, query = ast.query) {
|
||||
const toplevelFields: string[] = [];
|
||||
const nestedCollections: NestedCollectionAST[] = [];
|
||||
@@ -210,7 +83,10 @@ export default async function runAST(ast: AST, query = ast.query) {
|
||||
{
|
||||
column: 'id',
|
||||
operator: 'in',
|
||||
value: uniq(results.map((res) => res[batch.relation.field_many])),
|
||||
// filter removes null / undefined
|
||||
value: uniq(results.map((res) => res[batch.relation.field_many])).filter(
|
||||
(id) => id
|
||||
),
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -222,7 +98,8 @@ export default async function runAST(ast: AST, query = ast.query) {
|
||||
{
|
||||
column: batch.relation.field_many,
|
||||
operator: 'in',
|
||||
value: uniq(results.map((res) => res[batch.parentKey])),
|
||||
// filter removes null / undefined
|
||||
value: uniq(results.map((res) => res[batch.parentKey])).filter((id) => id),
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -234,9 +111,12 @@ export default async function runAST(ast: AST, query = ast.query) {
|
||||
if (m2o) {
|
||||
return {
|
||||
...record,
|
||||
[batch.fieldKey]: nestedResults.find((nestedRecord) => {
|
||||
return nestedRecord[batch.relation.primary_one] === record[batch.fieldKey];
|
||||
}),
|
||||
[batch.fieldKey]:
|
||||
nestedResults.find((nestedRecord) => {
|
||||
return (
|
||||
nestedRecord[batch.relation.primary_one] === record[batch.fieldKey]
|
||||
);
|
||||
}) || null,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ const validateQuery: RequestHandler = asyncHandler(async (req, res, next) => {
|
||||
const query: Query = req.sanitizedQuery;
|
||||
|
||||
await Promise.all([
|
||||
validateParams(req.params.collection, query),
|
||||
validateFields(req.params.collection, query),
|
||||
validateParams(req.collection, query),
|
||||
validateFields(req.collection, query),
|
||||
validateMeta(query),
|
||||
]);
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ const router = Router();
|
||||
const loginSchema = Joi.object({
|
||||
email: Joi.string().email().required(),
|
||||
password: Joi.string().required(),
|
||||
mode: Joi.string().valid('cookie', 'json'),
|
||||
});
|
||||
|
||||
router.post(
|
||||
|
||||
@@ -4,7 +4,7 @@ import sanitizeQuery from '../middleware/sanitize-query';
|
||||
import validateQuery from '../middleware/validate-query';
|
||||
import * as UsersService from '../services/users';
|
||||
import Joi from '@hapi/joi';
|
||||
import { InvalidPayloadException } from '../exceptions';
|
||||
import { InvalidPayloadException, InvalidCredentialsException } from '../exceptions';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
import * as ActivityService from '../services/activity';
|
||||
|
||||
@@ -41,6 +41,21 @@ router.get(
|
||||
})
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/me',
|
||||
useCollection('directus_users'),
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
if (!req.user) {
|
||||
throw new InvalidCredentialsException();
|
||||
}
|
||||
|
||||
const item = await UsersService.readUser(req.user, req.sanitizedQuery);
|
||||
return res.json({ data: item });
|
||||
})
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/:pk',
|
||||
useCollection('directus_users'),
|
||||
@@ -52,6 +67,31 @@ router.get(
|
||||
})
|
||||
);
|
||||
|
||||
router.patch(
|
||||
'/me',
|
||||
useCollection('directus_users'),
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
if (!req.user) {
|
||||
throw new InvalidCredentialsException();
|
||||
}
|
||||
|
||||
const item = await UsersService.updateUser(req.user, req.body, req.sanitizedQuery);
|
||||
|
||||
ActivityService.createActivity({
|
||||
action: ActivityService.Action.UPDATE,
|
||||
collection: req.collection,
|
||||
item: item.id,
|
||||
ip: req.ip,
|
||||
user_agent: req.get('user-agent'),
|
||||
action_by: req.user,
|
||||
});
|
||||
|
||||
return res.json({ data: item });
|
||||
})
|
||||
);
|
||||
|
||||
router.patch(
|
||||
'/:pk',
|
||||
useCollection('directus_users'),
|
||||
|
||||
@@ -21,7 +21,7 @@ export const authenticate = async (email: string, password?: string) => {
|
||||
* email to leak anywhere else.. We might have to make a dedicated "copy" of this function to
|
||||
* signal the difference
|
||||
*/
|
||||
if (password !== undefined && (await argon2.verify(password, user.password)) === false) {
|
||||
if (password !== undefined && (await argon2.verify(user.password, password)) === false) {
|
||||
throw new InvalidCredentialsException();
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ export const readItem = async <T = any>(
|
||||
query = {
|
||||
...query,
|
||||
filter: [
|
||||
...query.filter,
|
||||
...(query.filter || []),
|
||||
{
|
||||
column: primaryKeyField,
|
||||
operator: 'eq',
|
||||
|
||||
@@ -2,8 +2,12 @@ import { Query } from '../types/query';
|
||||
import * as ItemsService from './items';
|
||||
|
||||
export const readSettings = async (pk: string | number, query: Query) => {
|
||||
/** @TODO only fetch the one item that exists, or default to default values if it doesn't */
|
||||
return await ItemsService.readItem('directus_settings', pk, query);
|
||||
const settings = await ItemsService.readItems('directus_settings', {
|
||||
...query,
|
||||
limit: 1,
|
||||
});
|
||||
|
||||
return settings[0];
|
||||
};
|
||||
|
||||
export const updateSettings = async (
|
||||
|
||||
@@ -117,6 +117,8 @@ export default async function getAST(collection: string, query: Query): Promise<
|
||||
function getRelatedCollection(collection: string, field: string) {
|
||||
const relation = getRelation(collection, field);
|
||||
|
||||
if (!relation) return null;
|
||||
|
||||
if (relation.collection_many === collection && relation.field_many === field) {
|
||||
return relation.collection_one;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user