from starlette.testclient import TestClient from viano_bug_analysis.api.app import create_app from viano_bug_analysis.api.config import APIConfig,Project from viano_bug_analysis.api.keys import Keys def test_web_keys_reveal_auth_scope_revoke_and_restart(tmp_path): config=APIConfig(tmp_path,(Project('one','wow','vcore'),Project('two','wow','vcore')),()) app=create_app(config);app.state.sessions.users.manage('create_user','alice','password') client=TestClient(app) assert client.get('/v1/integration-keys').status_code==401 login=client.post('/v1/auth/login',json={'username':'alice','password':'password'}).json() headers={'X-CSRF-Token':login['csrf']} payload={'name':'Capture worker','projects':['one']} assert client.post('/v1/integration-keys',json=payload).status_code==403 assert client.post('/v1/integration-keys',headers=headers,json={**payload,'projects':['unknown']}).status_code==422 result=client.post('/v1/integration-keys',headers=headers,json=payload) assert result.status_code==200 identifier=result.json()['id'];base='/v1/integration-keys/'+identifier assert client.post(base+'/reveal').status_code==403 response=client.post(base+'/reveal',headers=headers) assert response.headers['cache-control']=='no-store' key=response.json()['key'] assert client.post(base+'/reveal',headers=headers).json()['key']==key listing=client.get('/v1/integration-keys').json() assert key not in str(listing) assert key.encode() not in (tmp_path/'runtime/integrations/keys.sqlite3').read_bytes() machine=TestClient(create_app(config));bearer={'Authorization':'Bearer '+key} assert machine.get('/v1/profiles',headers=bearer).json()['projects']==[{'project_id':'one','profile_id':'vcore','adapter':'vcore'}] assert machine.get('/v1/integration-keys',headers=bearer).status_code==403 assert machine.post(base+'/reveal',headers=bearer).status_code==403 assert machine.post('/v1/operations',headers=bearer,json={'action':'pause','project_id':'one'}).status_code==403 assert Keys(config).reveal(identifier)['key']==key (tmp_path/'runtime/integration-secrets/master.key').unlink() assert client.post(base+'/reveal',headers=headers).status_code==503 # Missing master must not silently generate a replacement; authentication can still use digest. assert not (tmp_path/'runtime/integration-secrets/master.key').exists() assert client.post(base+'/revoke',headers=headers).status_code==200 assert machine.get('/v1/profiles',headers=bearer).status_code==401 assert client.post(base+'/reveal',headers=headers).status_code==404