Resolved fernet issue.
This commit is contained in:
parent
83ac1eb001
commit
56b9aaa021
@ -1,9 +1,12 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import os
|
||||||
|
from cryptography.fernet import Fernet # Import Fernet
|
||||||
|
import dotenv # Import dotenv to reload env vars
|
||||||
|
|
||||||
def ensure_env_file_exists(env_path: Path):
|
def ensure_env_file_exists(env_path: Path):
|
||||||
"""
|
"""
|
||||||
Ensures that a .env file exists at the specified path.
|
Ensures that a .env file exists at the specified path.
|
||||||
If it doesn't exist, it creates one with default values.
|
If it doesn't exist, it creates one with default values (excluding SESSION_SECRET_KEY).
|
||||||
"""
|
"""
|
||||||
if not env_path.exists():
|
if not env_path.exists():
|
||||||
default_env_content = """# .env - Environment variables for Retoor's Cloud Solutions
|
default_env_content = """# .env - Environment variables for Retoor's Cloud Solutions
|
||||||
@ -47,6 +50,62 @@ SMTP_SENDER_EMAIL=no-reply@retoors.com
|
|||||||
else:
|
else:
|
||||||
print(f".env file already exists at {env_path}")
|
print(f".env file already exists at {env_path}")
|
||||||
|
|
||||||
|
def get_or_create_session_secret_key(env_path: Path) -> bytes:
|
||||||
|
"""
|
||||||
|
Retrieves the SESSION_SECRET_KEY from environment variables.
|
||||||
|
If not found or invalid, generates a new one, saves it to .env,
|
||||||
|
and reloads environment variables.
|
||||||
|
Returns the valid secret key as bytes.
|
||||||
|
"""
|
||||||
|
key_name = 'SESSION_SECRET_KEY'
|
||||||
|
|
||||||
|
# Try to get the key from already loaded environment variables
|
||||||
|
# This assumes dotenv.load_dotenv() has been called in main.py
|
||||||
|
secret_key_str = os.getenv(key_name)
|
||||||
|
|
||||||
|
# Variable to hold the key in bytes format
|
||||||
|
final_secret_key_bytes = None
|
||||||
|
|
||||||
|
if secret_key_str:
|
||||||
|
try:
|
||||||
|
# Fernet expects bytes, so encode the string from env var
|
||||||
|
final_secret_key_bytes = secret_key_str.encode('utf-8')
|
||||||
|
Fernet(final_secret_key_bytes) # Validate the key
|
||||||
|
print(f"Using existing valid {key_name} from environment.")
|
||||||
|
except ValueError:
|
||||||
|
print(f"Existing {key_name} in .env is invalid. Generating a new one.")
|
||||||
|
final_secret_key_bytes = None # Invalidate to trigger generation
|
||||||
|
|
||||||
|
if final_secret_key_bytes is None:
|
||||||
|
# Generate a new url-safe base64-encoded key
|
||||||
|
generated_key_bytes = Fernet.generate_key()
|
||||||
|
generated_key_str = generated_key_bytes.decode('utf-8')
|
||||||
|
|
||||||
|
# Append to .env file
|
||||||
|
with open(env_path, 'a') as f:
|
||||||
|
f.write(f'\n{key_name}={generated_key_str}\n')
|
||||||
|
|
||||||
|
print(f"Generated and added {key_name} to {env_path}")
|
||||||
|
|
||||||
|
# Reload environment variables to make the new key available for subsequent os.getenv calls
|
||||||
|
# This is important if other parts of the app might call os.getenv(key_name) later
|
||||||
|
dotenv.load_dotenv(dotenv_path=env_path)
|
||||||
|
|
||||||
|
final_secret_key_bytes = generated_key_bytes # Use the newly generated bytes directly
|
||||||
|
|
||||||
|
if final_secret_key_bytes is None:
|
||||||
|
raise RuntimeError(f"Failed to get or create {key_name}")
|
||||||
|
|
||||||
|
return final_secret_key_bytes
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Example usage:
|
# Example usage:
|
||||||
ensure_env_file_exists(Path(__file__).parent.parent.parent / ".env")
|
project_root = Path(__file__).parent.parent.parent
|
||||||
|
env_file = project_root / ".env"
|
||||||
|
ensure_env_file_exists(env_file)
|
||||||
|
try:
|
||||||
|
key = get_or_create_session_secret_key(env_file)
|
||||||
|
print(f"Session key obtained: {key}")
|
||||||
|
except RuntimeError as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
|||||||
@ -6,12 +6,13 @@ from aiohttp_session import setup as setup_session
|
|||||||
from aiohttp_session.cookie_storage import EncryptedCookieStorage
|
from aiohttp_session.cookie_storage import EncryptedCookieStorage
|
||||||
import os
|
import os
|
||||||
import aiojobs # Import aiojobs
|
import aiojobs # Import aiojobs
|
||||||
|
import dotenv # Import dotenv
|
||||||
|
|
||||||
from .routes import setup_routes
|
from .routes import setup_routes
|
||||||
from .services.user_service import UserService
|
from .services.user_service import UserService
|
||||||
from .services.config_service import ConfigService
|
from .services.config_service import ConfigService
|
||||||
from .middlewares import user_middleware, error_middleware
|
from .middlewares import user_middleware, error_middleware
|
||||||
from .helpers.env_manager import ensure_env_file_exists
|
from .helpers.env_manager import ensure_env_file_exists, get_or_create_session_secret_key # Import new function
|
||||||
|
|
||||||
|
|
||||||
async def setup_services(app: web.Application):
|
async def setup_services(app: web.Application):
|
||||||
@ -30,7 +31,9 @@ async def setup_services(app: web.Application):
|
|||||||
def create_app():
|
def create_app():
|
||||||
# Ensure .env file exists before loading any configurations
|
# Ensure .env file exists before loading any configurations
|
||||||
project_root = Path(__file__).parent.parent
|
project_root = Path(__file__).parent.parent
|
||||||
ensure_env_file_exists(project_root / ".env")
|
env_file_path = project_root / ".env" # Define env_file_path
|
||||||
|
ensure_env_file_exists(env_file_path)
|
||||||
|
dotenv.load_dotenv(dotenv_path=env_file_path) # Load environment variables after ensuring .env exists
|
||||||
|
|
||||||
app = web.Application()
|
app = web.Application()
|
||||||
|
|
||||||
@ -39,8 +42,8 @@ def create_app():
|
|||||||
app.middlewares.append(error_middleware)
|
app.middlewares.append(error_middleware)
|
||||||
|
|
||||||
# Setup session
|
# Setup session
|
||||||
secret_key = os.urandom(32)
|
secret_key = get_or_create_session_secret_key(env_file_path) # Use the new helper function
|
||||||
setup_session(app, EncryptedCookieStorage(secret_key))
|
setup_session(app, EncryptedCookieStorage(secret_key.decode("utf-8")))
|
||||||
|
|
||||||
app.middlewares.append(user_middleware)
|
app.middlewares.append(user_middleware)
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,8 @@ def setup_routes(app):
|
|||||||
app.router.add_view("/reset_password/{token}", ResetPasswordView, name="reset_password")
|
app.router.add_view("/reset_password/{token}", ResetPasswordView, name="reset_password")
|
||||||
app.router.add_view("/", SiteView, name="index")
|
app.router.add_view("/", SiteView, name="index")
|
||||||
app.router.add_view("/solutions", SiteView, name="solutions")
|
app.router.add_view("/solutions", SiteView, name="solutions")
|
||||||
|
app.router.add_view("/pricing", SiteView, name="pricing")
|
||||||
|
app.router.add_view("/security", SiteView, name="security")
|
||||||
app.router.add_view("/support", SiteView, name="support")
|
app.router.add_view("/support", SiteView, name="support")
|
||||||
app.router.add_view("/use_cases", SiteView, name="use_cases")
|
app.router.add_view("/use_cases", SiteView, name="use_cases")
|
||||||
app.router.add_view("/dashboard", SiteView, name="dashboard")
|
app.router.add_view("/dashboard", SiteView, name="dashboard")
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
<footer>
|
<footer aria-label="Site information and copyright">
|
||||||
<p>© 2025 Retoors. All rights reserved.</p>
|
<p>© 2025 Retoors. All rights reserved.</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@ -1,20 +1,20 @@
|
|||||||
<header>
|
<header>
|
||||||
<nav>
|
<nav aria-label="Main navigation">
|
||||||
<a href="/" class="logo">
|
<a href="/" class="logo" aria-label="Retoor's Cloud Solutions home">
|
||||||
<img src="/static/images/retoors-logo.svg" alt="Retoor's Cloud Solutions" />
|
<img src="/static/images/retoors-logo.svg" alt="Retoor's Cloud Solutions" />
|
||||||
<span>Retoor's Cloud Solutions</span>
|
<span>Retoor's Cloud Solutions</span>
|
||||||
</a>
|
</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/solutions">Solutions</a></li>
|
<li><a href="/solutions" aria-label="Our Solutions">Solutions</a></li>
|
||||||
<li><a href="/pricing">Pricing</a></li>
|
<li><a href="/pricing" aria-label="Pricing Plans">Pricing</a></li>
|
||||||
<li><a href="/security">Security</a></li>
|
<li><a href="/security" aria-label="Security Information">Security</a></li>
|
||||||
<li><a href="/support">Support</a></li>
|
<li><a href="/support" aria-label="Support Page">Support</a></li>
|
||||||
{% if request['user'] %}
|
{% if request['user'] %}
|
||||||
<li><a href="/dashboard">Dashboard</a></li>
|
<li><a href="/dashboard" aria-label="User Dashboard">Dashboard</a></li>
|
||||||
<li><a href="/logout" class="btn-nav">Logout</a></li>
|
<li><a href="/logout" class="btn-nav" aria-label="Logout">Logout</a></li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li><a href="/login" class="btn-outline-nav">Sign In</a></li>
|
<li><a href="/login" class="btn-outline-nav" aria-label="Sign In to your account">Sign In</a></li>
|
||||||
<li><a href="/register" class="btn-primary-nav">Start Your Free Trial</a></li>
|
<li><a href="/register" class="btn-primary-nav" aria-label="Start your free trial">Start Your Free Trial</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@ -5,10 +5,12 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{% block title %}Retoors Storage{% endblock %}</title>
|
<title>{% block title %}Retoors Storage{% endblock %}</title>
|
||||||
<link rel="stylesheet" href="/static/css/base.css">
|
<link rel="stylesheet" href="/static/css/base.css">
|
||||||
|
<link rel="stylesheet" href="/static/css/components/footer.css">
|
||||||
|
<link rel="stylesheet" href="/static/css/components/content_pages.css"> {# Added for content page styling #}
|
||||||
{% block head %}{% endblock %}
|
{% block head %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{% include 'components/navigation.html' %}
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user