feat: qualify native Hermes research and private conversation exports
This commit is contained in:
1 parent
fb3178d34b
commit
e048793b02
5 files changed
+206
-6
No files matched your search
@@ -0,0 +1,64 @@
|
||||
"""Offline owned exports; no Hermes/LiveKit/deployment calls."""
|
||||
import pytest
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from control.accounts import Accounts
|
||||
from control.app import Settings
|
||||
from control.chat_exports import create_export_router, export_conversation
|
||||
from control.chat_store import ChatStore
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def env(tmp_path):
|
||||
accounts = Accounts(str(tmp_path / 'accounts.db'))
|
||||
users = [accounts.create(name, name, 'user', 'correct-horse-password') for name in ('alice', 'bob')]
|
||||
tokens = [accounts.issue_session(u['id'], 3600, u['password_hash'])[0] for u in users]
|
||||
store = ChatStore(accounts)
|
||||
conversation = store.create_conversation(users[0]['id'], title='Private')
|
||||
store.add_message(users[0]['id'], conversation['id'], 'user', 'Original question')
|
||||
store.add_message(users[0]['id'], conversation['id'], 'assistant', '<script>untrusted</script> [Source](https://example.test)')
|
||||
app = FastAPI()
|
||||
app.state.accounts = accounts
|
||||
app.state.settings = Settings()
|
||||
app.state.chat_store = store
|
||||
app.include_router(create_export_router())
|
||||
with TestClient(app) as client:
|
||||
yield accounts, store, client, users, tokens, conversation
|
||||
accounts.close()
|
||||
|
||||
|
||||
def test_full_projection_and_safe_markdown(env):
|
||||
accounts, store, client, users, tokens, conversation = env
|
||||
headers = {'Authorization': 'Bearer ' + tokens[0]}
|
||||
url = '/api/conversations/' + conversation['id'] + '/export'
|
||||
response = client.get(url, headers=headers)
|
||||
assert response.status_code == 200
|
||||
document = response.json()
|
||||
assert len(document['messages']) == 2
|
||||
assert document['messages'][0]['content'] == 'Original question'
|
||||
assert 'hermes_session_id' not in response.text
|
||||
assert response.headers['cache-control'] == 'no-store'
|
||||
assert response.headers['content-disposition'].startswith('attachment;')
|
||||
markdown = client.get(url + '?format=markdown', headers=headers)
|
||||
assert markdown.status_code == 200
|
||||
assert markdown.headers['content-type'].startswith('text/plain')
|
||||
assert '[Source](https://example.test)' in markdown.text
|
||||
assert '<script>untrusted</script>' in markdown.text
|
||||
assert client.get(url + '?format=html', headers=headers).status_code == 422
|
||||
|
||||
|
||||
def test_owned_revoked_deleted_and_bounded(env):
|
||||
accounts, store, client, users, tokens, conversation = env
|
||||
url = '/api/conversations/' + conversation['id'] + '/export'
|
||||
assert client.get(url).status_code == 401
|
||||
assert client.get(url, headers={'Authorization': 'Bearer ' + tokens[1]}).status_code == 404
|
||||
with pytest.raises(HTTPException) as error:
|
||||
export_conversation(store, users[0]['id'], conversation['id'], byte_limit=4)
|
||||
assert error.value.status_code == 413
|
||||
accounts.revoke(tokens[0])
|
||||
assert client.get(url, headers={'Authorization': 'Bearer ' + tokens[0]}).status_code == 401
|
||||
store.delete_conversation(users[0]['id'], conversation['id'])
|
||||
with pytest.raises(HTTPException) as error:
|
||||
export_conversation(store, users[0]['id'], conversation['id'])
|
||||
assert error.value.status_code == 404
|
||||
Reference in new issue
Block a user