From d719c7cd65f409f8bac62201617394f5e1e67359 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Mon, 14 Aug 2023 19:05:24 +0800 Subject: [PATCH 1/2] fix: issue 599, throw error if the given user context doesn't contain full id fields --- .../runtime/src/enhancements/policy/index.ts | 17 +++++++++++++++++ .../tests/enhancements/with-policy/auth.test.ts | 6 +----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/runtime/src/enhancements/policy/index.ts b/packages/runtime/src/enhancements/policy/index.ts index 5ed4eeea2..2894e795f 100644 --- a/packages/runtime/src/enhancements/policy/index.ts +++ b/packages/runtime/src/enhancements/policy/index.ts @@ -5,9 +5,11 @@ import path from 'path'; import semver from 'semver'; import { PRISMA_MINIMUM_VERSION } from '../../constants'; import { AuthUser, DbClientContract } from '../../types'; +import { hasAllFields } from '../../validation'; import { getDefaultModelMeta } from '../model-meta'; import { makeProxy } from '../proxy'; import type { ModelMeta, PolicyDef, ZodSchemas } from '../types'; +import { getIdFields } from '../utils'; import { PolicyProxyHandler } from './handler'; /** @@ -70,6 +72,21 @@ export function withPolicy( const _modelMeta = options?.modelMeta ?? getDefaultModelMeta(); const _zodSchemas = options?.zodSchemas ?? getDefaultZodSchemas(); + // validate user context + if (context?.user) { + const idFields = getIdFields(_modelMeta, 'User', true); + if ( + !hasAllFields( + context.user, + idFields.map((f) => f.name) + ) + ) { + throw new Error( + `Invalid user context: must have valid ID field ${idFields.map((f) => `"${f.name}"`).join(', ')}` + ); + } + } + return makeProxy( prisma, _modelMeta, diff --git a/tests/integration/tests/enhancements/with-policy/auth.test.ts b/tests/integration/tests/enhancements/with-policy/auth.test.ts index fb7e0c9b5..a2dfc1b86 100644 --- a/tests/integration/tests/enhancements/with-policy/auth.test.ts +++ b/tests/integration/tests/enhancements/with-policy/auth.test.ts @@ -113,8 +113,7 @@ describe('With Policy: auth() test', () => { const authDb = withPolicy(); await expect(authDb.post.update({ where: { id: '1' }, data: { title: 'bcd' } })).toBeRejectedByPolicy(); - const authDb1 = withPolicy({ id: null }); - await expect(authDb1.post.update({ where: { id: '1' }, data: { title: 'bcd' } })).rejects.toThrow(); + expect(() => withPolicy({ id: null })).toThrow(/Invalid user context/); const authDb2 = withPolicy({ id: 'user1' }); await expect(authDb2.post.update({ where: { id: '1' }, data: { title: 'bcd' } })).toResolveTruthy(); @@ -148,9 +147,6 @@ describe('With Policy: auth() test', () => { await expect(db.post.update({ where: { id: '1' }, data: { title: 'bcd' } })).toBeRejectedByPolicy(); - const authDb1 = withPolicy({ id: null }); - await expect(authDb1.post.update({ where: { id: '1' }, data: { title: 'bcd' } })).rejects.toThrow(); - const authDb2 = withPolicy({ id: 'user1' }); await expect(authDb2.post.update({ where: { id: '1' }, data: { title: 'bcd' } })).toResolveTruthy(); }); From 0a603df94f0309e2b5678e060cab1002b25a66a4 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Mon, 14 Aug 2023 19:26:30 +0800 Subject: [PATCH 2/2] fixes --- packages/runtime/src/enhancements/policy/index.ts | 2 +- packages/runtime/src/enhancements/utils.ts | 8 ++++++-- .../enhancements/with-policy/multi-id-fields.test.ts | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/runtime/src/enhancements/policy/index.ts b/packages/runtime/src/enhancements/policy/index.ts index 2894e795f..3da47b86a 100644 --- a/packages/runtime/src/enhancements/policy/index.ts +++ b/packages/runtime/src/enhancements/policy/index.ts @@ -74,7 +74,7 @@ export function withPolicy( // validate user context if (context?.user) { - const idFields = getIdFields(_modelMeta, 'User', true); + const idFields = getIdFields(_modelMeta, 'User'); if ( !hasAllFields( context.user, diff --git a/packages/runtime/src/enhancements/utils.ts b/packages/runtime/src/enhancements/utils.ts index 4ba822f3c..e2d286da0 100644 --- a/packages/runtime/src/enhancements/utils.ts +++ b/packages/runtime/src/enhancements/utils.ts @@ -18,9 +18,13 @@ export function getModelFields(data: object) { * Gets id fields for the given model. */ export function getIdFields(modelMeta: ModelMeta, model: string, throwIfNotFound = false) { - const fields = modelMeta.fields[lowerCaseFirst(model)]; + let fields = modelMeta.fields[lowerCaseFirst(model)]; if (!fields) { - throw new Error(`Unable to load fields for ${model}`); + if (throwIfNotFound) { + throw new Error(`Unable to load fields for ${model}`); + } else { + fields = {}; + } } const result = Object.values(fields).filter((f) => f.isId); if (result.length === 0 && throwIfNotFound) { diff --git a/tests/integration/tests/enhancements/with-policy/multi-id-fields.test.ts b/tests/integration/tests/enhancements/with-policy/multi-id-fields.test.ts index 7dd62364a..f48cdba45 100644 --- a/tests/integration/tests/enhancements/with-policy/multi-id-fields.test.ts +++ b/tests/integration/tests/enhancements/with-policy/multi-id-fields.test.ts @@ -124,7 +124,7 @@ describe('With Policy: multiple id fields', () => { await prisma.user.create({ data: { x: '1', y: '1' } }); await prisma.user.create({ data: { x: '1', y: '2' } }); - const anonDb = withPolicy({}); + const anonDb = withPolicy(); await expect( anonDb.m.create({ data: { owner: { connect: { x_y: { x: '1', y: '2' } } } } })