diff --git a/scripts/test_admin_config_browser.py b/scripts/test_admin_config_browser.py deleted file mode 100755 index 8721cbe..0000000 --- a/scripts/test_admin_config_browser.py +++ /dev/null @@ -1,124 +0,0 @@ -from pathlib import Path -import json -import os -import re -from playwright.sync_api import sync_playwright - -ROOT=Path(__file__).resolve().parents[1] -admin=ROOT/'src/admin' -router=(admin/'router.rs').read_text() -main=router.split('fn admin_app_javascript()',1)[1].split('fn admin_vhosts_javascript()',1)[0] -web=admin/'web' -vhosts=['core.js','protocol.js','health.js','rates.js','editor.js','render.js'] -chunk='\n'.join((web/'vhosts'/f).read_text() for f in vhosts) -app=['"use strict";', 'const ADMIN_DASHBOARD_DEFAULTS = Object.freeze('+ (web/'dashboard-defaults.json').read_text()+');'] -parts=re.findall(r'include_str!\("(web/[^"\n]+)"\)|(?{\n'+chunk+'\n})();') -js='\n'.join(app) -startup='if (document.readyState === "complete") startAdminPanel();\nelse document.addEventListener("DOMContentLoaded", startAdminPanel, { once: true });' -assert startup in js, 'runtime script bootstrap not found' -js=js.replace(startup,'// Browser mock harness: startup disabled') -# App JS is reconstructed in the same module order as router.rs. - -html=(web/'index.html').read_text() -for marker,rel,split in [('RP_METRICS_MAIN','partials/overview-metrics.html',''),('RP_CHARTS_MAIN','partials/overview-charts.html','')]: - raw=(web/rel).read_text(); one,two=raw.split(split) - html=html.replace(f'',one).replace(f'',two) -html=re.sub(r']*src="/assets/app_[^\"]+"[^>]*>', '', html) -html=re.sub(r']*href="/assets/style_[^\"]+"[^>]*>', '', html) -html=html.replace('__RUSTPROXY_VERSION__','0.34.13') - -mock_cfg={ - 'global_security': {'user_agent_blocking':{'enabled':True,'patterns':['bad-bot','curl/*']},'country_access':{'mode':'block','countries':['RU']},'acl':None,'method_policy':{'mode':'block','methods':['TRACE']},'content_type_policy':{'enabled':False,'blocked':[]},'rate_limit':{'enabled':False,'requests':100,'window_seconds':60,'burst':20},'security_headers':{'hsts':{'enabled':False,'max_age_seconds':31536000,'include_subdomains':False,'preload':False},'nosniff':True,'frame_options':'deny','referrer_policy':None,'content_security_policy':None,'permissions_policy':None}}, - 'geoip_updates':{'enabled':False,'format':'csv_pair','ipv4_url':'','ipv6_url':'','mmdb_url':'','max_bytes':1000000,'interval_seconds':86400}, - 'logging': {'capture_user_agent': True, 'capture_country': False,'file':{'enabled':False},'loki':{'enabled':False},'logstash':{'enabled':False},'format':{}}, - 'error_log':{'enabled':False,'path':'/var/log/rustproxy/error.log','format':'JSON'}, - 'cache':{},'transform':{},'compression':{},'server_header':{},'diagnostic_headers':{}, - 'vhosts':[],'redirects':[],'streams':[],'not_found_hosts':[],'host_policies':[],'acl_profiles':[],'listeners':{},'tls':{}, -} -with sync_playwright() as p: - browser=p.chromium.launch(headless=True,executable_path='/usr/bin/chromium',args=['--no-sandbox','--disable-dev-shm-usage']) - page=browser.new_page() - page.set_default_timeout(4000) - errors=[] - page.on('pageerror',lambda exc: errors.append(str(exc))) - page.set_content(html,wait_until='load') - page.evaluate('''() => { window.__calls=[]; window.__mockFetch=async function(path,options={}) { - const request={path:typeof path==='string'?path:path.url,method:options.method||'GET',body:options.body?JSON.parse(options.body):null}; - __calls.push(request); - const reply=JSON.parse(JSON.stringify(envelope||{revision:0,config:{}})); - if (request.method==='PUT') { - if (request.path==='/api/config/global-security') reply.config.global_security=request.body.value; - if (request.path==='/api/config/logging') {reply.config.logging=request.body.value.logging;reply.config.error_log=request.body.value.error_log;} - if (request.path==='/api/config/geoip') reply.config.geoip_updates=request.body.value; - reply.revision+=1; - } - if(request.method==='POST' && request.path==='/api/config/geoip/update')return new Response(JSON.stringify({outcome:'current'}),{status:200,headers:{'content-type':'application/json'}}); - return new Response(JSON.stringify(reply),{status:200,headers:{'content-type':'application/json'}}); - }; window.fetch=window.__mockFetch; }''') - try: - page.add_script_tag(content=js) - except Exception as e: - print('INIT ERRORS',errors) - raise - print('script page errors:', errors[:8]); assert not errors, errors - page.evaluate('''(config) => {authenticated=true; csrf='test'; envelope={revision:10,config}; - renderConfig=()=>{}; refresh=async()=>{}; renderSettings();}''',mock_cfg) - assert not errors,errors - print('initial global UA:',page.locator('#global-ua-block-patterns').input_value()) - # Global rules save: UA + header untouched - page.locator('#global-ua-block-patterns').evaluate('(el)=>{el.value="bad-bot\\nvery-bad";el.dispatchEvent(new Event("input",{bubbles:true}));}') - page.locator('#global-security-form').evaluate('(form)=>form.dispatchEvent(new Event("submit",{bubbles:true,cancelable:true}))') - page.wait_for_function('window.__calls.length >= 1') - result=page.evaluate('window.__calls.at(-1)') - print('global rules save',result['path'],result['body']['value']['user_agent_blocking'],result['body']['value']['security_headers']['frame_options']) - assert result['path']=='/api/config/global-security' - assert result['body']['value']['user_agent_blocking']['patterns']==['bad-bot','very-bad'] - assert result['body']['value']['security_headers']['frame_options']=='deny' - page.wait_for_timeout(200) - # Global headers save: UA untouched, changed nosniff - page.locator('#global-nosniff').evaluate('(el)=>{el.checked=false;el.dispatchEvent(new Event("change",{bubbles:true}));}') - page.locator('#global-security-headers-form').evaluate('(form)=>form.dispatchEvent(new Event("submit",{bubbles:true,cancelable:true}))') - page.wait_for_function('window.__calls.length >= 2') - result=page.evaluate('window.__calls.at(-1)') - print('global headers save',result['path'],result['body']['value']['user_agent_blocking'],result['body']['value']['security_headers']['nosniff']) - assert result['body']['value']['user_agent_blocking']['patterns']==['bad-bot','very-bad'] - assert result['body']['value']['security_headers']['nosniff']==False - page.wait_for_timeout(200) - # GeoIP triggered as action not section save - page.locator('#geoip-update-now').evaluate('(el)=>el.click()') - page.wait_for_function('window.__calls.some(x=>x.method==="POST" && x.path==="/api/config/geoip/update")') - result=page.evaluate('window.__calls.at(-1)') - print('geoip update',result['method'],result['path']) - assert result['path']=='/api/config/geoip/update' - # Error-log subsection must save logging and error_log together. - page.evaluate('renderSettings()') - page.locator('#error-log-enabled').evaluate('(el)=>{el.checked=true;el.dispatchEvent(new Event("change",{bubbles:true}));}') - page.locator('#error-log-form').evaluate('(form)=>form.dispatchEvent(new Event("submit",{bubbles:true,cancelable:true}))') - page.wait_for_function('window.__calls.some(x=>x.path==="/api/config/logging" && x.method==="PUT")') - result=page.evaluate('window.__calls.at(-1)') - print('logging group save',result['path'],list(result['body']['value'])) - assert result['path']=='/api/config/logging' - assert set(result['body']['value'])=={'logging','error_log'} - assert result['body']['value']['error_log']['enabled']==True - assert result['body']['value']['logging']['capture_user_agent']==True - page.wait_for_timeout(120) - # GeoIP settings are saved through its section, while update remains POST. - page.evaluate('renderSettings()') - page.locator('#geoip-interval-hours').evaluate('(el)=>{el.value="48";el.dispatchEvent(new Event("input",{bubbles:true}));}') - page.locator('#geoip-form').evaluate('(form)=>form.dispatchEvent(new Event("submit",{bubbles:true,cancelable:true}))') - page.wait_for_function('window.__calls.some(x=>x.path==="/api/config/geoip" && x.method==="PUT")') - result=page.evaluate('window.__calls.at(-1)') - print('geoip section save',result['path'],result['body']['value']['interval_seconds']) - assert result['path']=='/api/config/geoip' - assert result['body']['value']['interval_seconds']==48*3600 - assert result['body']['expected_revision']==13 - print('browser final errors',errors[:10]); assert not errors,errors - browser.close()