Release v0.7.2.2 - DirectX Download and Install Fixes

This commit is contained in:
Omni
2026-08-10 16:43:38 +01:00
parent 22bf5e30e5
commit 7e2121c334
13 changed files with 302 additions and 218 deletions
@@ -1,110 +1,20 @@
"""
Nexus OAuth callback: _generate_self_signed_cert, _create_callback_handler, _wait_for_callback.
Nexus OAuth callback: _wait_for_callback.
Callback delivery is the jackify:// protocol handler (registered by
NexusOAuthProtocolMixin), which writes code+state to oauth_callback.tmp for this
method to poll. There is no localhost HTTP server in this flow.
"""
import os
import time
import logging
import tempfile
import urllib.parse
from pathlib import Path
from http.server import BaseHTTPRequestHandler
from typing import Optional, Tuple
logger = logging.getLogger(__name__)
class NexusOAuthCallbackMixin:
"""Mixin providing callback server and wait logic for NexusOAuthService."""
def _generate_self_signed_cert(self) -> Tuple[Optional[str], Optional[str]]:
"""Generate self-signed certificate for HTTPS localhost. Returns (cert_file_path, key_file_path) or (None, None)."""
redirect_host = getattr(self, 'REDIRECT_HOST', '127.0.0.1')
try:
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
import datetime
import ipaddress
logger.info("Generating self-signed certificate for OAuth callback")
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, "US"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Jackify"),
x509.NameAttribute(NameOID.COMMON_NAME, redirect_host),
])
cert = x509.CertificateBuilder().subject_name(subject).issuer_name(issuer).public_key(
private_key.public_key()
).serial_number(x509.random_serial_number()).not_valid_before(
datetime.datetime.now(datetime.UTC)
).not_valid_after(
datetime.datetime.now(datetime.UTC) + datetime.timedelta(days=365)
).add_extension(
x509.SubjectAlternativeName([x509.IPAddress(ipaddress.IPv4Address(redirect_host))]),
critical=False,
).sign(private_key, hashes.SHA256())
temp_dir = tempfile.mkdtemp()
cert_file = os.path.join(temp_dir, "oauth_cert.pem")
key_file = os.path.join(temp_dir, "oauth_key.pem")
with open(cert_file, "wb") as f:
f.write(cert.public_bytes(serialization.Encoding.PEM))
with open(key_file, "wb") as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
))
return cert_file, key_file
except ImportError:
logger.error("cryptography package not installed - required for OAuth")
return None, None
except Exception as e:
logger.error("Failed to generate SSL certificate: %s", e)
return None, None
def _create_callback_handler(self):
"""Create HTTP request handler class for OAuth callback."""
service = self
class OAuthCallbackHandler(BaseHTTPRequestHandler):
def log_message(self, format, *args):
logger.debug("OAuth callback: %s", format % args)
def do_GET(self):
logger.info("OAuth callback received: %s", self.path)
parsed = urllib.parse.urlparse(self.path)
params = urllib.parse.parse_qs(parsed.query)
if parsed.path == '/favicon.ico':
self.send_response(404)
self.end_headers()
return
if 'code' in params:
service._auth_code = params['code'][0]
service._auth_state = params.get('state', [None])[0]
logger.info("OAuth authorization code received: %s...", service._auth_code[:10])
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
html = """<html><head><title>Authorization Successful</title></head><body style="font-family: Arial, sans-serif; text-align: center; padding: 50px;"><h1>Authorization Successful!</h1><p>You can close this window and return to Jackify.</p><script>setTimeout(function() { window.close(); }, 3000);</script></body></html>"""
self.wfile.write(html.encode())
elif 'error' in params:
service._auth_error = params['error'][0]
error_desc = params.get('error_description', ['Unknown error'])[0]
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
html = f"<html><head><title>Authorization Failed</title></head><body style='font-family: Arial, sans-serif; text-align: center; padding: 50px;'><h1>Authorization Failed</h1><p>Error: {service._auth_error}</p><p>{error_desc}</p><p>You can close this window and try again in Jackify.</p></body></html>"
self.wfile.write(html.encode())
else:
logger.warning("OAuth callback with no code or error: %s", params)
self.send_response(400)
self.send_header('Content-type', 'text/html')
self.end_headers()
html = "<html><head><title>Invalid Request</title></head><body style='font-family: Arial, sans-serif; text-align: center; padding: 50px;'><h1>Invalid OAuth Callback</h1><p>You can close this window.</p></body></html>"
self.wfile.write(html.encode())
service._server_done.set()
logger.debug("OAuth callback handler signaled server to shut down")
return OAuthCallbackHandler
"""Mixin providing callback wait logic for NexusOAuthService."""
def _wait_for_callback(self) -> bool:
"""Wait for OAuth callback via jackify:// protocol handler. Returns True if callback received."""