| 123456789101112131415161718192021222324 |
- // @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})}
- })
|