video_monitor/tests/windows_integration.py

104 lines
6.5 KiB
Python
Raw Normal View History

2026-09-04 18:16:14 +08:00
"""Run separately: all database, keys and configuration live in a temporary directory."""
import base64
import json
import os
from pathlib import Path
import sys
import tempfile
import time
from unittest.mock import patch
ROOT=Path(__file__).resolve().parents[1]
sys.path.insert(0,str(ROOT))
def main():
with tempfile.TemporaryDirectory(prefix='monitor-部署-test-') as tmp:
os.environ.update(MONITOR_DESKTOP='1',MONITOR_DATA_DIR=tmp,
DJANGO_SETTINGS_MODULE='framework.settings',
MONITOR_DEV_PUBLIC_KEY=str(Path(tmp)/'public.pem'))
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
key=Ed25519PrivateKey.generate()
Path(tmp,'public.pem').write_bytes(key.public_key().public_bytes(serialization.Encoding.PEM,serialization.PublicFormat.SubjectPublicKeyInfo))
from monitor_runtime.bootstrap import prepare_files,initialize_database
prepare_files()
initialize_database()
from django.test import Client
from django.contrib.auth import get_user_model
from monitor_runtime import web, licensing
from monitor_runtime.paths import data,atomic_json
from django.core.files.uploadedfile import SimpleUploadedFile
fingerprint='v1:'+'b'*64
checks=[]
with patch.object(licensing,'machine_identity',return_value={'fingerprint':fingerprint,'weak_uuid':False}):
client=Client(enforce_csrf_checks=True,HTTP_HOST='localhost')
local={'REMOTE_ADDR':'127.0.0.1'}
remote={'REMOTE_ADDR':'192.168.1.5'}
assert client.get('/setup',**remote).status_code==403
assert client.get('/setup',**local).status_code==200
csrf=client.cookies['csrftoken'].value
assert client.post('/license/request',{'setup_token':web.SETUP_TOKEN},**local).status_code==403
assert client.post('/license/request',{'setup_token':'wrong'},HTTP_X_CSRFTOKEN=csrf,**local).status_code==403
result=client.post('/license/request',{'setup_token':web.SETUP_TOKEN},HTTP_X_CSRFTOKEN=csrf,**local)
assert result.status_code==200 and result.json()['fingerprint']==fingerprint
checks.append('local-only bootstrap, one-time token and CSRF')
from datetime import datetime,timezone,timedelta
payload={'schema_version':1,'product':'monitor','license_id':'integration','customer':'integration-test',
'machine_fingerprint':fingerprint,'issued_at':datetime.now(timezone.utc).isoformat(),'expires_at':None}
document={'payload':payload,'signature':base64.b64encode(key.sign(licensing.canonical(payload))).decode()}
uploaded=SimpleUploadedFile('license.json',json.dumps(document).encode(),content_type='application/json')
result=client.post('/license/import',{'setup_token':web.SETUP_TOKEN,'license':uploaded},HTTP_X_CSRFTOKEN=csrf,**local)
assert result.status_code==200,result.content[:200]
assert licensing.check_license()['valid']
checks.append('signed import and DPAPI clock persistence')
with patch('monitor_runtime.bootstrap.local_addresses',return_value=['192.168.1.10']):
result=client.post('/setup',{'setup_token':web.SETUP_TOKEN,'username':'owner',
'password':'Different!7826Secure','confirm':'Different!7826Secure','address':'192.168.1.10'},
HTTP_X_CSRFTOKEN=csrf,**local)
assert result.status_code==200,result.content[:200]
assert get_user_model().objects.filter(is_superuser=True).count()==1
assert client.get('/setup',**local).status_code==403
assert client.post('/license/request',{'setup_token':web.SETUP_TOKEN},HTTP_X_CSRFTOKEN=csrf,**local).status_code==403
checks.append('first administrator and permanently closed setup')
snapshot=data('static/storage/alarm/test.jpg');snapshot.parent.mkdir(parents=True,exist_ok=True);snapshot.write_bytes(b'image')
assert client.get('/static/storage/alarm/test.jpg',**local).status_code==403
client.force_login(get_user_model().objects.get(username='owner'))
response=client.get('/static/storage/alarm/test.jpg',**local)
assert response.status_code==200
response.close()
assert client.get('/static/storage/../../.runtime-secrets.json',**local).status_code in (403,404)
assert client.get('/license/status',**local).status_code==200
checks.append('authenticated private files and administrator license status')
old_secret=data('.runtime-secrets.json').read_bytes()
initialize_database()
assert data('.runtime-secrets.json').read_bytes()==old_secret
assert get_user_model().objects.filter(username='owner').count()==1
checks.append('idempotent database initialization preserves users and encryption key')
payload['expires_at']=(datetime.now(timezone.utc)-timedelta(seconds=1)).isoformat()
document={'payload':payload,'signature':base64.b64encode(key.sign(licensing.canonical(payload))).decode()}
atomic_json(data('license.json'),document)
assert not licensing.check_license()['valid']
assert client.get('/analysis/openStatus',**local).status_code==403
assert client.get('/license/status',**local).status_code==200
checks.append('expiry blocks APIs and leaves renewal available')
payload['expires_at']=None
document={'payload':payload,'signature':base64.b64encode(key.sign(licensing.canonical(payload))).decode()}
licensing.import_license(json.dumps(document).encode())
with patch.object(licensing.time,'time',return_value=time.time()-1000):
assert not licensing.check_license()['valid']
checks.append('renewal and clock rollback detection')
get_user_model().objects.all().delete()
assert client.get('/setup',**local).status_code==403
checks.append('initialization stays closed even after administrator deletion')
from django.db import connections
connections.close_all()
import logging
logging.shutdown()
for handler in list(logging.getLogger().handlers):
logging.getLogger().removeHandler(handler)
handler.close()
print(json.dumps({'passed':checks},ensure_ascii=False,indent=2))
if __name__=='__main__':
main()