fix: hidden fields being mutated on patch (#2317)
This commit is contained in:
@@ -140,7 +140,7 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
|||||||
entityConfig: collectionConfig,
|
entityConfig: collectionConfig,
|
||||||
req,
|
req,
|
||||||
overrideAccess: true,
|
overrideAccess: true,
|
||||||
showHiddenFields,
|
showHiddenFields: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// /////////////////////////////////////
|
// /////////////////////////////////////
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export const restrictedVersionsSlug = 'restricted-versions';
|
|||||||
export const siblingDataSlug = 'sibling-data';
|
export const siblingDataSlug = 'sibling-data';
|
||||||
export const relyOnRequestHeadersSlug = 'rely-on-request-headers';
|
export const relyOnRequestHeadersSlug = 'rely-on-request-headers';
|
||||||
export const docLevelAccessSlug = 'doc-level-access';
|
export const docLevelAccessSlug = 'doc-level-access';
|
||||||
|
export const hiddenFieldsSlug = 'hidden-fields';
|
||||||
|
|
||||||
const openAccess = {
|
const openAccess = {
|
||||||
create: () => true,
|
create: () => true,
|
||||||
@@ -242,6 +243,46 @@ export default buildConfig({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
slug: hiddenFieldsSlug,
|
||||||
|
access: openAccess,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'title',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'partiallyHiddenGroup',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'value',
|
||||||
|
type: 'text',
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'partiallyHiddenArray',
|
||||||
|
type: 'array',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'value',
|
||||||
|
type: 'text',
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
onInit: async (payload) => {
|
onInit: async (payload) => {
|
||||||
await payload.create({
|
await payload.create({
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import payload from '../../src';
|
import payload from '../../src';
|
||||||
import type { Options as CreateOptions } from '../../src/collections/operations/local/create';
|
|
||||||
import { Forbidden } from '../../src/errors';
|
import { Forbidden } from '../../src/errors';
|
||||||
import type { PayloadRequest } from '../../src/types';
|
import type { PayloadRequest } from '../../src/types';
|
||||||
import { initPayloadTest } from '../helpers/configHelpers';
|
import { initPayloadTest } from '../helpers/configHelpers';
|
||||||
import { relyOnRequestHeadersSlug, requestHeaders, restrictedSlug, siblingDataSlug, slug } from './config';
|
import { hiddenFieldsSlug, relyOnRequestHeadersSlug, requestHeaders, restrictedSlug, siblingDataSlug, slug } from './config';
|
||||||
import type { Restricted, Post, RelyOnRequestHeader } from './payload-types';
|
import type { Restricted, Post, RelyOnRequestHeader } from './payload-types';
|
||||||
import { firstArrayText, secondArrayText } from './shared';
|
import { firstArrayText, secondArrayText } from './shared';
|
||||||
|
|
||||||
@@ -34,7 +33,38 @@ describe('Access Control', () => {
|
|||||||
await payload.mongoMemoryServer.stop();
|
await payload.mongoMemoryServer.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.todo('should properly prevent / allow public users from reading a restricted field');
|
it('should not affect hidden fields when patching data', async () => {
|
||||||
|
const doc = await payload.create({
|
||||||
|
collection: hiddenFieldsSlug,
|
||||||
|
data: {
|
||||||
|
partiallyHiddenArray: [{
|
||||||
|
name: 'public_name',
|
||||||
|
value: 'private_value',
|
||||||
|
}],
|
||||||
|
partiallyHiddenGroup: {
|
||||||
|
name: 'public_name',
|
||||||
|
value: 'private_value',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await payload.update({
|
||||||
|
collection: hiddenFieldsSlug,
|
||||||
|
id: doc.id,
|
||||||
|
data: {
|
||||||
|
title: 'Doc Title',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatedDoc = await payload.findByID({
|
||||||
|
collection: hiddenFieldsSlug,
|
||||||
|
id: doc.id,
|
||||||
|
showHiddenFields: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(updatedDoc.partiallyHiddenGroup.value).toEqual('private_value');
|
||||||
|
expect(updatedDoc.partiallyHiddenArray[0].value).toEqual('private_value');
|
||||||
|
});
|
||||||
|
|
||||||
it('should be able to restrict access based upon siblingData', async () => {
|
it('should be able to restrict access based upon siblingData', async () => {
|
||||||
const { id } = await payload.create({
|
const { id } = await payload.create({
|
||||||
@@ -220,7 +250,7 @@ describe('Access Control', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async function createDoc<Collection>(data: Partial<Collection>, overrideSlug = slug, options?: Partial<CreateOptions<Collection>>): Promise<Collection> {
|
async function createDoc<Collection>(data: Partial<Collection>, overrideSlug = slug, options?: Partial<Collection>): Promise<Collection> {
|
||||||
return payload.create({
|
return payload.create({
|
||||||
...options,
|
...options,
|
||||||
collection: overrideSlug,
|
collection: overrideSlug,
|
||||||
|
|||||||
@@ -5,11 +5,20 @@
|
|||||||
* and re-run `payload generate:types` to regenerate this file.
|
* and re-run `payload generate:types` to regenerate this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export interface Config {}
|
export interface Config {
|
||||||
/**
|
collections: {
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
users: User;
|
||||||
* via the `definition` "users".
|
posts: Post;
|
||||||
*/
|
restricted: Restricted;
|
||||||
|
'read-only-collection': ReadOnlyCollection;
|
||||||
|
'restricted-versions': RestrictedVersion;
|
||||||
|
'sibling-data': SiblingDatum;
|
||||||
|
'rely-on-request-headers': RelyOnRequestHeader;
|
||||||
|
'doc-level-access': DocLevelAccess;
|
||||||
|
'hidden-fields': HiddenField;
|
||||||
|
};
|
||||||
|
globals: {};
|
||||||
|
}
|
||||||
export interface User {
|
export interface User {
|
||||||
id: string;
|
id: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
@@ -19,15 +28,12 @@ export interface User {
|
|||||||
lockUntil?: string;
|
lockUntil?: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
password?: string;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
|
||||||
* via the `definition` "posts".
|
|
||||||
*/
|
|
||||||
export interface Post {
|
export interface Post {
|
||||||
id: string;
|
id: string;
|
||||||
restrictedField?: string;
|
restrictedField?: string;
|
||||||
group: {
|
group?: {
|
||||||
restrictedGroupText?: string;
|
restrictedGroupText?: string;
|
||||||
};
|
};
|
||||||
restrictedRowText?: string;
|
restrictedRowText?: string;
|
||||||
@@ -35,43 +41,27 @@ export interface Post {
|
|||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
|
||||||
* via the `definition` "restricted".
|
|
||||||
*/
|
|
||||||
export interface Restricted {
|
export interface Restricted {
|
||||||
id: string;
|
id: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
|
||||||
* via the `definition` "read-only-collection".
|
|
||||||
*/
|
|
||||||
export interface ReadOnlyCollection {
|
export interface ReadOnlyCollection {
|
||||||
id: string;
|
id: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
|
||||||
* via the `definition` "restricted-versions".
|
|
||||||
*/
|
|
||||||
export interface RestrictedVersion {
|
export interface RestrictedVersion {
|
||||||
id: string;
|
id: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
|
||||||
* via the `definition` "sibling-data".
|
|
||||||
*/
|
|
||||||
export interface SiblingDatum {
|
export interface SiblingDatum {
|
||||||
id: string;
|
id: string;
|
||||||
array: {
|
array?: {
|
||||||
allowPublicReadability?: boolean;
|
allowPublicReadability?: boolean;
|
||||||
text?: string;
|
text?: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
@@ -79,20 +69,12 @@ export interface SiblingDatum {
|
|||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
|
||||||
* via the `definition` "rely-on-request-headers".
|
|
||||||
*/
|
|
||||||
export interface RelyOnRequestHeader {
|
export interface RelyOnRequestHeader {
|
||||||
id: string;
|
id: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
|
||||||
* via the `definition` "doc-level-access".
|
|
||||||
*/
|
|
||||||
export interface DocLevelAccess {
|
export interface DocLevelAccess {
|
||||||
id: string;
|
id: string;
|
||||||
approvedForRemoval?: boolean;
|
approvedForRemoval?: boolean;
|
||||||
@@ -101,3 +83,18 @@ export interface DocLevelAccess {
|
|||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
|
export interface HiddenField {
|
||||||
|
id: string;
|
||||||
|
title?: string;
|
||||||
|
partiallyHiddenGroup?: {
|
||||||
|
name?: string;
|
||||||
|
value?: string;
|
||||||
|
};
|
||||||
|
partiallyHiddenArray?: {
|
||||||
|
name?: string;
|
||||||
|
value?: string;
|
||||||
|
id?: string;
|
||||||
|
}[];
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user