mirror of
https://github.com/strapi/strapi.git
synced 2025-12-29 16:16:20 +00:00
Make locale/localizations private for non-localized cts (#21495)
This commit is contained in:
parent
e8787bcc0d
commit
7f39880265
@ -3,6 +3,7 @@ import type { Core } from '@strapi/types';
|
||||
|
||||
import validateLocaleCreation from './controllers/validate-locale-creation';
|
||||
import graphqlProvider from './graphql';
|
||||
import { getService } from './utils';
|
||||
|
||||
export default ({ strapi }: { strapi: Core.Strapi }) => {
|
||||
extendContentTypes(strapi);
|
||||
@ -38,12 +39,16 @@ const addContentManagerLocaleMiddleware = (strapi: Core.Strapi) => {
|
||||
* @param {Strapi} strapi
|
||||
*/
|
||||
const extendContentTypes = (strapi: Core.Strapi) => {
|
||||
const { isLocalizedContentType } = getService('content-types');
|
||||
|
||||
Object.values(strapi.contentTypes).forEach((contentType) => {
|
||||
const { attributes } = contentType;
|
||||
|
||||
const isLocalized = isLocalizedContentType(contentType);
|
||||
|
||||
_.set(attributes, 'locale', {
|
||||
writable: true,
|
||||
private: false,
|
||||
private: !isLocalized,
|
||||
configurable: false,
|
||||
visible: false,
|
||||
type: 'string',
|
||||
@ -54,7 +59,7 @@ const extendContentTypes = (strapi: Core.Strapi) => {
|
||||
relation: 'oneToMany',
|
||||
target: contentType.uid,
|
||||
writable: false,
|
||||
private: false,
|
||||
private: !isLocalized,
|
||||
configurable: false,
|
||||
visible: false,
|
||||
unstable_virtual: true,
|
||||
|
||||
@ -4,12 +4,14 @@ import localizations from './localizations';
|
||||
import locales from './locales';
|
||||
import isoLocales from './iso-locales';
|
||||
import contentTypes from './content-types';
|
||||
import sanitize from './sanitize';
|
||||
|
||||
export default {
|
||||
permissions,
|
||||
metrics,
|
||||
localizations,
|
||||
locales,
|
||||
sanitize,
|
||||
'iso-locales': isoLocales,
|
||||
'content-types': contentTypes,
|
||||
};
|
||||
|
||||
42
packages/plugins/i18n/server/src/services/sanitize/index.ts
Normal file
42
packages/plugins/i18n/server/src/services/sanitize/index.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import type { Core, Schema, Data } from '@strapi/types';
|
||||
|
||||
import { traverseEntity } from '@strapi/utils';
|
||||
import { curry } from 'lodash/fp';
|
||||
|
||||
import { getService } from '../../utils';
|
||||
|
||||
const LOCALIZATION_FIELDS = ['locale', 'localizations'];
|
||||
|
||||
const sanitize = ({ strapi }: { strapi: Core.Strapi }) => {
|
||||
const { isLocalizedContentType } = getService('content-types');
|
||||
|
||||
/**
|
||||
* Sanitizes localization fields of a given entity based on its schema.
|
||||
*
|
||||
* Remove localization-related fields that are unnecessary, that is
|
||||
* for schemas that aren't localized.
|
||||
*/
|
||||
const sanitizeLocalizationFields = curry((schema: Schema.Schema, entity: Data.Entity) =>
|
||||
traverseEntity(
|
||||
({ key, schema }, { remove }) => {
|
||||
const isLocalized = isLocalizedContentType(schema);
|
||||
const isLocalizationField = LOCALIZATION_FIELDS.includes(key);
|
||||
|
||||
if (!isLocalized && isLocalizationField) {
|
||||
remove(key);
|
||||
}
|
||||
},
|
||||
{ schema, getModel: strapi.getModel.bind(strapi) },
|
||||
entity
|
||||
)
|
||||
);
|
||||
|
||||
return {
|
||||
sanitizeLocalizationFields,
|
||||
};
|
||||
};
|
||||
|
||||
type SanitizeService = typeof sanitize;
|
||||
|
||||
export default sanitize;
|
||||
export type { SanitizeService };
|
||||
@ -4,6 +4,7 @@ import type { ContentTypesService } from '../services/content-types';
|
||||
import type { MetricsService } from '../services/metrics';
|
||||
import type { ISOLocalesService } from '../services/iso-locales';
|
||||
import type { LocalizationsService } from '../services/localizations';
|
||||
import type { SanitizeService } from '../services/sanitize';
|
||||
|
||||
type S = {
|
||||
permissions: PermissionsService;
|
||||
@ -12,6 +13,7 @@ type S = {
|
||||
localizations: LocalizationsService;
|
||||
['iso-locales']: ISOLocalesService;
|
||||
['content-types']: ContentTypesService;
|
||||
sanitize: SanitizeService;
|
||||
};
|
||||
|
||||
const getCoreStore = () => {
|
||||
|
||||
@ -1,10 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const { ApplicationError, ValidationError } = require('@strapi/utils').errors;
|
||||
const { async, errors } = require('@strapi/utils');
|
||||
const { getService } = require('../utils');
|
||||
const { validateDeleteRoleBody } = require('./validation/user');
|
||||
|
||||
const { ApplicationError, ValidationError } = errors;
|
||||
|
||||
const sanitizeOutput = async (role) => {
|
||||
const { sanitizeLocalizationFields } = strapi.plugin('i18n').service('sanitize');
|
||||
const schema = strapi.getModel('plugin::users-permissions.role');
|
||||
|
||||
return async.pipe(sanitizeLocalizationFields(schema))(role);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Default action.
|
||||
@ -30,13 +39,17 @@ module.exports = {
|
||||
return ctx.notFound();
|
||||
}
|
||||
|
||||
ctx.send({ role });
|
||||
const safeRole = await sanitizeOutput(role);
|
||||
|
||||
ctx.send({ role: safeRole });
|
||||
},
|
||||
|
||||
async find(ctx) {
|
||||
const roles = await getService('role').find();
|
||||
|
||||
ctx.send({ roles });
|
||||
const safeRoles = await Promise.all(roles.map(sanitizeOutput));
|
||||
|
||||
ctx.send({ roles: safeRoles });
|
||||
},
|
||||
|
||||
async updateRole(ctx) {
|
||||
|
||||
@ -191,10 +191,9 @@ describe('Search query', () => {
|
||||
|
||||
expect(Array.isArray(res.body.results)).toBe(true);
|
||||
expect(res.body.results.length).toBe(data.beds.length);
|
||||
// TODO V5: Filter out i18n fields if content type is not localized
|
||||
expect(res.body.results.map(omit([...CREATOR_FIELDS, 'localizations', 'status']))).toEqual(
|
||||
expect.arrayContaining(data.beds)
|
||||
);
|
||||
expect(
|
||||
res.body.results.map(omit([...CREATOR_FIELDS, 'locale', 'localizations', 'status']))
|
||||
).toEqual(expect.arrayContaining(data.beds));
|
||||
});
|
||||
|
||||
test('search with special characters', async () => {
|
||||
|
||||
@ -26,7 +26,6 @@ const expectArticle = (letter: string) => {
|
||||
return {
|
||||
id,
|
||||
title,
|
||||
locale: 'en',
|
||||
documentId: expect.any(String),
|
||||
publishedAt: expect.anything(),
|
||||
updatedAt: expect.anything(),
|
||||
@ -108,24 +107,20 @@ const fixtures = {
|
||||
category: (fixtures) => [
|
||||
{
|
||||
name: 'Category A',
|
||||
locale: 'en',
|
||||
tags: fixtures.tag.filter((tag) => tag.name.endsWith('B')).map((cat) => cat.id),
|
||||
},
|
||||
{
|
||||
name: 'Category C',
|
||||
locale: 'en',
|
||||
tags: fixtures.tag
|
||||
.filter((tag) => tag.name.endsWith('D') || tag.name.endsWith('A'))
|
||||
.map((cat) => cat.id),
|
||||
},
|
||||
{
|
||||
name: 'Category B',
|
||||
locale: 'en',
|
||||
tags: fixtures.tag.filter((tag) => tag.name.endsWith('C')).map((cat) => cat.id),
|
||||
},
|
||||
{
|
||||
name: 'Category D',
|
||||
locale: 'en',
|
||||
tags: fixtures.tag.filter((tag) => tag.name.endsWith('A')).map((cat) => cat.id),
|
||||
},
|
||||
],
|
||||
@ -134,24 +129,20 @@ const fixtures = {
|
||||
return [
|
||||
{
|
||||
title: 'Article A',
|
||||
locale: 'en',
|
||||
categories: fixtures.category.filter((cat) => cat.name.endsWith('B')).map((cat) => cat.id),
|
||||
},
|
||||
{
|
||||
title: 'Article C',
|
||||
locale: 'en',
|
||||
categories: fixtures.category.filter((cat) => cat.name.endsWith('D')).map((cat) => cat.id),
|
||||
},
|
||||
{
|
||||
title: 'Article D',
|
||||
locale: 'en',
|
||||
categories: fixtures.category
|
||||
.filter((cat) => cat.name.endsWith('A') || cat.name.endsWith('D'))
|
||||
.map((cat) => cat.id),
|
||||
},
|
||||
{
|
||||
title: 'Article B',
|
||||
locale: 'en',
|
||||
categories: fixtures.category
|
||||
.filter((cat) => cat.name.endsWith('C') || cat.name.endsWith('D'))
|
||||
.map((cat) => cat.id),
|
||||
|
||||
@ -776,7 +776,6 @@ describe('Core API - Validate', () => {
|
||||
// TODO: Sanitize id field
|
||||
'id',
|
||||
'documentId',
|
||||
'locale',
|
||||
'name',
|
||||
'name_non_searchable',
|
||||
'name_hidden',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user