Spaces:
Sleeping
Sleeping
from flask import Flask, render_template, send_from_directory, Response | |
import os | |
import uuid | |
import time | |
from functools import wraps | |
app = Flask(__name__, static_folder='static') | |
# Configure session-based token security | |
app.config['SECRET_KEY'] = str(uuid.uuid4()) | |
app.config['SESSION_TYPE'] = 'filesystem' | |
app.config['PERMANENT_SESSION_LIFETIME'] = 1800 # 30 minutes | |
# Store for valid tokens and their expiry times (in a real app, use a proper database) | |
VALID_TOKENS = {} | |
TOKEN_EXPIRY = 3600 # 1 hour | |
# Security headers for all responses | |
def add_security_headers(response): | |
# Prevent content from being framed by other sites | |
response.headers['X-Frame-Options'] = 'DENY' | |
# Prevent browsers from performing MIME sniffing | |
response.headers['X-Content-Type-Options'] = 'nosniff' | |
# Enable XSS protection in browsers | |
response.headers['X-XSS-Protection'] = '1; mode=block' | |
# Content Security Policy to restrict resources | |
response.headers['Content-Security-Policy'] = "default-src 'self' https://cdn.tailwindcss.com https://cdnjs.cloudflare.com https://fonts.googleapis.com https://fonts.gstatic.com; img-src 'self' data:; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://fonts.googleapis.com https://cdn.tailwindcss.com; script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com https://cdnjs.cloudflare.com https://cdn.jsdelivr.net" | |
# Cache control - prevent caching | |
response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0' | |
response.headers['Pragma'] = 'no-cache' | |
response.headers['Expires'] = '0' | |
return response | |
# Load the HTML content | |
with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'dist', 'index.html'), 'r') as f: | |
html_content = f.read() | |
# Add anti-inspection/download JavaScript to the HTML | |
def add_protection_scripts(html): | |
# Insert scripts right before the closing body tag | |
protection_scripts = """ | |
<script> | |
// Disable right-click context menu | |
document.addEventListener('contextmenu', e => e.preventDefault()); | |
// Disable keyboard shortcuts that could be used to save the page | |
document.addEventListener('keydown', function(e) { | |
// Ctrl/Cmd + S (Save) | |
if ((e.ctrlKey || e.metaKey) && e.keyCode === 83) { | |
e.preventDefault(); | |
return false; | |
} | |
// Ctrl/Cmd + P (Print, which can be used to save as PDF) | |
if ((e.ctrlKey || e.metaKey) && e.keyCode === 80) { | |
e.preventDefault(); | |
return false; | |
} | |
// Ctrl/Cmd + Shift + I or F12 (Developer Tools) | |
if (((e.ctrlKey || e.metaKey) && e.shiftKey && e.keyCode === 73) || e.keyCode === 123) { | |
e.preventDefault(); | |
return false; | |
} | |
// Ctrl/Cmd + U (View Source) | |
if ((e.ctrlKey || e.metaKey) && e.keyCode === 85) { | |
e.preventDefault(); | |
return false; | |
} | |
}); | |
// Detect and prevent developer tools from opening with periodic check | |
(function() { | |
function detectDevTools() { | |
const widthThreshold = window.outerWidth - window.innerWidth > 160; | |
const heightThreshold = window.outerHeight - window.innerHeight > 160; | |
if (widthThreshold || heightThreshold) { | |
document.body.innerHTML = '<div style="text-align: center; padding: 50px;"><h1>Developer tools detected</h1><p>Please close developer tools to view this content.</p></div>'; | |
} | |
} | |
// Check periodically | |
setInterval(detectDevTools, 1000); | |
})(); | |
// Make content uncopyable | |
document.addEventListener('selectstart', e => e.preventDefault()); | |
document.addEventListener('copy', e => e.preventDefault()); | |
// Add a watermark with user info and timestamp | |
(function() { | |
const watermark = document.createElement('div'); | |
watermark.style.position = 'fixed'; | |
watermark.style.top = '0'; | |
watermark.style.left = '0'; | |
watermark.style.width = '100%'; | |
watermark.style.height = '100%'; | |
watermark.style.pointerEvents = 'none'; | |
watermark.style.display = 'flex'; | |
watermark.style.justifyContent = 'center'; | |
watermark.style.alignItems = 'center'; | |
watermark.style.zIndex = '10000'; | |
const watermarkText = document.createElement('p'); | |
watermarkText.style.transform = 'rotate(-45deg)'; | |
watermarkText.style.fontSize = '20px'; | |
watermarkText.style.color = 'rgba(0, 0, 0, 0.1)'; | |
watermarkText.style.userSelect = 'none'; | |
// Update watermark with current time every minute | |
function updateWatermark() { | |
const date = new Date(); | |
watermarkText.textContent = 'Balance Academy - ' + date.toLocaleString(); | |
} | |
updateWatermark(); | |
setInterval(updateWatermark, 60000); | |
watermark.appendChild(watermarkText); | |
document.body.appendChild(watermark); | |
})(); | |
// Additional anti-inspection code, tries to detect if devtools is open | |
(function() { | |
let devtools = function() {}; | |
devtools.toString = function() { | |
document.body.innerHTML = '<div style="text-align: center; padding: 50px;"><h1>Developer tools detected</h1><p>Please close developer tools to view this content.</p></div>'; | |
return 'Dev tools usage detected!'; | |
}; | |
console.log('%c', devtools); | |
})(); | |
</script> | |
""" | |
return html.replace('</body>', protection_scripts + '</body>') | |
protected_html = add_protection_scripts(html_content) | |
# Create a simple token-based authentication system | |
def generate_token(): | |
token = str(uuid.uuid4()) | |
VALID_TOKENS[token] = time.time() + TOKEN_EXPIRY | |
return token | |
def is_valid_token(token): | |
if token in VALID_TOKENS: | |
if time.time() < VALID_TOKENS[token]: | |
return True | |
else: | |
# Token expired | |
del VALID_TOKENS[token] | |
return False | |
def clean_expired_tokens(): | |
current_time = time.time() | |
expired = [token for token, expiry in VALID_TOKENS.items() if current_time > expiry] | |
for token in expired: | |
del VALID_TOKENS[token] | |
# Authentication decorator | |
def token_required(f): | |
def decorated_function(*args, **kwargs): | |
token = kwargs.get('token') | |
if not token or not is_valid_token(token): | |
return Response('Unauthorized access', 401) | |
return f(*args, **kwargs) | |
return decorated_function | |
# Routes | |
def index(): | |
token = generate_token() | |
clean_expired_tokens() | |
return render_template('login.html', token=token) | |
def view_content(token): | |
return protected_html | |
def serve_static(filename): | |
return send_from_directory(app.static_folder, filename) | |
if __name__ == '__main__': | |
os.makedirs(os.path.join(os.path.dirname(__file__), 'static'), exist_ok=True) | |
os.makedirs(os.path.join(os.path.dirname(__file__), 'templates'), exist_ok=True) | |
app.run(host='0.0.0.0', port=7860, debug=False) |