// @vitest-environment node import {it,expect,vi} from 'vitest' import Koa from 'koa' import {bodyParser} from '@koa/bodyparser' import request from 'supertest' import {mkdtempSync,rmSync} from 'node:fs' import {tmpdir} from 'node:os' import {join} from 'node:path' import {randomUUID} from 'node:crypto' import {WorkspaceStore} from '../../src/server/workspaceStore' import {ImageManagementService} from '../../src/server/imageManagement' import {HttpError} from '../../src/server/errors' it('restricts image operations to admins and fences job grants to user version and Runner',async()=>{ const home=mkdtempSync(join(tmpdir(),'yaoyao-image-route-')),store=new WorkspaceStore(home);let version=1,active=true const auth:any={requireAdmin:(ctx:any)=>{if(ctx.get('x-admin')!=='yes')throw new HttpError(403,'管理员权限','admin_required');return {id:'owner'}},isAdminActive:()=>active,pushAuthorizationVersion:()=>version} const images=vi.fn(async(owner:string,runnerId:string,p:any)=>({owner,runnerId,job:{id:p.id}})),service=new ImageManagementService(store,auth,{images} as any),app=new Koa();app.use(async(ctx,next)=>{try{await next()}catch(e){ctx.status=(e as any).status||500;ctx.body={error:String(e)}}});app.use(bodyParser());app.use(service.router().routes()) try{const runner=randomUUID(),id=randomUUID(),base=`/api/app/admin/runners/${runner}/images` await request(app.callback()).post(base+'/jobs').send({requestId:id,operation:'prepare'}).expect(403);expect(images).not.toHaveBeenCalled() await request(app.callback()).post(base+'/jobs').set('x-admin','yes').send({requestId:id,operation:'prepare',path:'/etc/passwd'}).expect(400) await request(app.callback()).post(base+'/jobs').set('x-admin','yes').send({requestId:id,operation:'prepare'}).expect(202) expect(service.allowed(id,runner)).toBe(true);expect(service.allowed(id,randomUUID())).toBe(false) version++;expect(service.allowed(id,runner)).toBe(false);version--;active=false;expect(service.allowed(id,runner)).toBe(false) }finally{store.close();rmSync(home,{recursive:true,force:true})} })