Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(history): handle sanitization when fetching versions #20212

Merged
merged 19 commits into from Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -59,16 +59,28 @@ const LinkEllipsis = styled(Link)`

const CustomRelationInput = (props: RelationsFieldProps) => {
const { formatMessage } = useIntl();
const field = useField<{ results: RelationResult[]; meta: { missingCount: number } }>(props.name);
const { results, meta } = field.value!;
const field = useField<
{ results: RelationResult[]; meta: { missingCount: number } } | RelationResult[]
>(props.name);

const fieldValue = field.value!;

const res = Array.isArray(fieldValue)
? {
results: fieldValue,
meta: { missingCount: 0 },
}
: fieldValue;

const { results, meta } = res;

return (
<Box>
<FieldLabel>{props.label}</FieldLabel>
{results.length > 0 && (
<Flex direction="column" gap={2} marginTop={1} alignItems="stretch">
{results.map((relationData) => {
// @ts-expect-error targetModel does exist on the attribute. But it's not typed.
// @ts-expect-error - targetModel does exist on the attribute. But it's not typed.
const href = `../${COLLECTION_TYPES}/${props.attribute.targetModel}/${relationData.documentId}`;
const label = getRelationLabel(relationData, props.mainField);

Expand Down
@@ -1,4 +1,4 @@
import { errors } from '@strapi/utils';
import { async, errors } from '@strapi/utils';
import type { Core, UID } from '@strapi/types';
import { getService as getContentManagerService } from '../../utils';
import { getService } from '../utils';
Expand Down Expand Up @@ -68,13 +68,18 @@ const createHistoryVersionController = ({ strapi }: { strapi: Core.Strapi }) =>
...getValidPagination({ page: params.page, pageSize: params.pageSize }),
});

const sanitizedResults = await async.map(results, async (version: any) => {
return {
markkaylor marked this conversation as resolved.
Show resolved Hide resolved
...version,
data: await permissionChecker.sanitizeOutput({
...version.data,
locale: version.locale.code,
}),
};
});

return {
data: await Promise.all(
results.map(async (result) => ({
...result,
data: await permissionChecker.sanitizeOutput(result.data),
}))
),
data: sanitizedResults,
meta: { pagination },
};
},
Expand Down
Expand Up @@ -354,9 +354,43 @@ const createHistoryService = ({ strapi }: { strapi: Core.Strapi }) => {
): Promise<CreateHistoryVersion['data']> => {
const entryWithRelations = await Object.entries(entry.schema).reduce(
async (currentDataWithRelations, [attributeKey, attributeSchema]) => {
/**
* Don't build the relations response object for relations to admin users,
* because it breaks the pickAllowedAdminUserFields sanitization, as it looks for the
*/
if (
attributeSchema.type === 'relation' &&
attributeSchema.relation !== 'morphToOne' &&
attributeSchema.relation !== 'morphToMany' &&
attributeSchema.target === 'admin::user'
) {
const attributeValue = entry.data[attributeKey];
const attributeValues = Array.isArray(attributeValue)
? attributeValue
: [attributeValue];

return {
...(await currentDataWithRelations),
[attributeKey]: (
await Promise.all(
attributeValues.map((userToPopulate) => {
if (userToPopulate == null) {
return null;
}

return strapi
.query('admin::user')
.findOne({ where: { id: userToPopulate.id } });
})
)
).filter((user) => user != null),
markkaylor marked this conversation as resolved.
Show resolved Hide resolved
};
}

// TODO: handle relations that are inside components
if (['relation', 'media'].includes(attributeSchema.type)) {
const attributeValue = entry.data[attributeKey];

const relationResponse = await buildRelationReponse(
(Array.isArray(attributeValue)
? attributeValue
Expand Down