@@ -55,6 +55,10 @@ vi.mock('@/lib/users/queries', () => ({
5555 requireResolvedUserEmail : ( emails : Map < string , string > , userId : string ) => emails . get ( userId ) ! ,
5656} ) )
5757
58+ import {
59+ InsufficientWorkspacePermissionsError ,
60+ NoWorkspaceAccessError ,
61+ } from '@/lib/core/application'
5862import { OrchestrationError } from '@/lib/core/orchestration/types'
5963import { DELETE , GET , PATCH } from '@/app/api/v2/files/[fileId]/route'
6064
@@ -136,9 +140,7 @@ describe('v2 single-file routes', () => {
136140 } )
137141
138142 it ( 'conceals download authorization failures' , async ( ) => {
139- mocks . download . mockRejectedValue (
140- new OrchestrationError ( 'forbidden' , 'Insufficient workspace permissions' )
141- )
143+ mocks . download . mockRejectedValue ( new NoWorkspaceAccessError ( ) )
142144
143145 const response = await GET (
144146 new NextRequest ( `http://localhost:3000/api/v2/files/${ FILE_ID } ?workspaceId=${ WORKSPACE_ID } ` ) ,
@@ -166,7 +168,7 @@ describe('v2 single-file routes', () => {
166168 } )
167169 } )
168170
169- it ( 'maps rename conflicts and conceals authorization failures ' , async ( ) => {
171+ it ( 'maps rename conflicts and conceals absent workspace access ' , async ( ) => {
170172 mocks . rename . mockRejectedValueOnce ( new OrchestrationError ( 'conflict' , 'Name exists' ) )
171173 const conflict = await PATCH (
172174 new NextRequest ( `http://localhost:3000/api/v2/files/${ FILE_ID } ` , {
@@ -178,9 +180,7 @@ describe('v2 single-file routes', () => {
178180 )
179181 expect ( conflict . status ) . toBe ( 409 )
180182
181- mocks . rename . mockRejectedValueOnce (
182- new OrchestrationError ( 'forbidden' , 'Insufficient workspace permissions' )
183- )
183+ mocks . rename . mockRejectedValueOnce ( new NoWorkspaceAccessError ( ) )
184184 const concealed = await PATCH (
185185 new NextRequest ( `http://localhost:3000/api/v2/files/${ FILE_ID } ` , {
186186 method : 'PATCH' ,
@@ -192,6 +192,23 @@ describe('v2 single-file routes', () => {
192192 expect ( concealed . status ) . toBe ( 404 )
193193 } )
194194
195+ it ( 'returns forbidden when the current workspace role cannot rename the file' , async ( ) => {
196+ mocks . rename . mockRejectedValueOnce ( new InsufficientWorkspacePermissionsError ( ) )
197+ const response = await PATCH (
198+ new NextRequest ( `http://localhost:3000/api/v2/files/${ FILE_ID } ` , {
199+ method : 'PATCH' ,
200+ headers : { 'Content-Type' : 'application/json' } ,
201+ body : JSON . stringify ( { workspaceId : WORKSPACE_ID , name : 'renamed.csv' } ) ,
202+ } ) ,
203+ context
204+ )
205+
206+ expect ( response . status ) . toBe ( 403 )
207+ expect ( await response . json ( ) ) . toEqual ( {
208+ error : { code : 'FORBIDDEN' , message : 'Insufficient workspace permissions' } ,
209+ } )
210+ } )
211+
195212 it ( 'archives through the same principal and operation pipeline' , async ( ) => {
196213 const request = new NextRequest (
197214 `http://localhost:3000/api/v2/files/${ FILE_ID } ?workspaceId=${ WORKSPACE_ID } ` ,
0 commit comments