ChatGPT's update to harden software and run db updates.

This commit is contained in:
2026-10-21 06:53:45 -04:00
parent 1e63076123
commit acc8cb70f5
171 changed files with 9325 additions and 404 deletions
+22 -1
View File
@@ -20,7 +20,8 @@ class Application:
if not os.environ.get('HCR_TEST_DSN'):
raise RuntimeError('An isolated HCR_TEST_DSN is required.')
self.env=os.environ.copy()
self.env.update(HCR_APPLICATION_URL='',HCR_ENVIRONMENT='Development')
self.env['HCR_MFA_KEY']='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='
self.env.update(HCR_SUPER_ADMIN_EMAIL='',HCR_APPLICATION_URL='',HCR_ENVIRONMENT='Development',HCR_SMTP_HOST='127.0.0.1',HCR_SMTP_PORT='1',HCR_SMTP_USER='test@example.test',HCR_SMTP_PASSWORD='test-only',HCR_SMTP_FROM='test@example.test')
self.database=self.fixture('create')['database']
self.env['HCR_DB_NAME']=self.database
with socket.socket() as available:
@@ -52,7 +53,27 @@ class Application:
_,body,_=self.request()
status,body,_=self.request(data={'action':'SignIn.login','csrf_token':self.csrf(body),'user_email':email,'user_password':password})
if status!=200 or b'name="csrf-token"' not in body:raise AssertionError('Login failed: '+body[:500].decode(errors='replace'))
if b'<h1>Account security</h1>' in body:
if b'setup key' in body:
secret=re.search(rb'<pre>([A-Z2-7]+)</pre>',body).group(1).decode()
code=self.totp(secret)
status,body,_=self.request(data={'action':'security','csrf_token':self.csrf(body),'current_password':password,'mfa_code':code})
if b'Save your recovery codes' not in body:raise AssertionError(body[:1000])
recovery=re.findall(rb'\b[a-f0-9]{32}\b',body)
self.recovery=[c.decode() for c in recovery]
status,body,_=self.request()
else:
code=self.fixture('mfaCode',email)['code']
status,body,_=self.request(data={'action':'security','csrf_token':self.csrf(body),'current_password':password,'mfa_code':code})
if status!=200:raise AssertionError('MFA failed: '+str(status))
self.token=self.csrf(body)
@staticmethod
def totp(secret, at=None):
import base64,hashlib,hmac,struct,time
secret=base64.b32decode(secret+'='*((8-len(secret)%8)%8))
digest=hmac.new(secret,struct.pack('>Q',int((time.time() if at is None else at)//30)),hashlib.sha1).digest()
offset=digest[-1]&15
return str((int.from_bytes(digest[offset:offset+4],'big')&0x7fffffff)%1000000).zfill(6)
def post(self,action,**values):
return self.request(data={'action':action,'csrf_token':self.token,**values},ajax=True)
def logout(self):self.post('signout')