Ver 30.023 env var
This commit is contained in:
parent
60ee21dd61
commit
8cf355d603
37
core/temp_env_view.py
Normal file
37
core/temp_env_view.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from django.shortcuts import render
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.contrib.admin.views.decorators import staff_member_required
|
||||||
|
|
||||||
|
@staff_member_required
|
||||||
|
def setup_env(request):
|
||||||
|
# BASE_DIR is usually workspace, so its parent is where .env is.
|
||||||
|
env_path = Path(os.getcwd()).parent / ".env"
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
# Extract secrets from form
|
||||||
|
secret_key = request.POST.get("DJANGO_SECRET_KEY", "").strip()
|
||||||
|
email_user = request.POST.get("EMAIL_HOST_USER", "").strip()
|
||||||
|
email_pass = request.POST.get("EMAIL_HOST_PASSWORD", "").strip()
|
||||||
|
|
||||||
|
existing_content = ""
|
||||||
|
if env_path.exists():
|
||||||
|
existing_content = env_path.read_text()
|
||||||
|
|
||||||
|
with open(env_path, "a") as f:
|
||||||
|
# Add a newline if the file doesn't end with one
|
||||||
|
if existing_content and not existing_content.endswith("\n"):
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
|
# Append only non-empty values
|
||||||
|
if secret_key:
|
||||||
|
f.write(f"DJANGO_SECRET_KEY={secret_key}\n")
|
||||||
|
if email_user:
|
||||||
|
f.write(f"EMAIL_HOST_USER={email_user}\n")
|
||||||
|
if email_pass:
|
||||||
|
f.write(f"EMAIL_HOST_PASSWORD={email_pass}\n")
|
||||||
|
|
||||||
|
return HttpResponse("<h3>Success! Secrets safely appended to .env.</h3><p>Please return to the AI chat, ask me to restart the app, and then I will delete this temporary page.</p>")
|
||||||
|
|
||||||
|
return render(request, "core/temp_env_setup.html")
|
||||||
45
core/templates/core/temp_env_setup.html
Normal file
45
core/templates/core/temp_env_setup.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Secure Environment Setup</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: sans-serif; padding: 2rem; max-width: 600px; margin: auto; }
|
||||||
|
.form-group { margin-bottom: 1.5rem; }
|
||||||
|
label { display: block; font-weight: bold; margin-bottom: 0.5rem; }
|
||||||
|
input[type="text"], input[type="password"] {
|
||||||
|
width: 100%; padding: 0.5rem; font-size: 1rem;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
padding: 0.75rem 1.5rem; font-size: 1rem; background-color: #007bff; color: white; border: none; cursor: pointer;
|
||||||
|
}
|
||||||
|
button:hover { background-color: #0056b3; }
|
||||||
|
.warning { color: red; font-size: 0.85rem; margin-bottom: 2rem; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Secure Environment Setup</h2>
|
||||||
|
<p class="warning">Warning: This page is temporary and should be deleted immediately after you save your secrets. Only administrators can view this page.</p>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="DJANGO_SECRET_KEY">DJANGO_SECRET_KEY</label>
|
||||||
|
<input type="text" id="DJANGO_SECRET_KEY" name="DJANGO_SECRET_KEY" placeholder="Paste your Secret Key">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="EMAIL_HOST_USER">EMAIL_HOST_USER</label>
|
||||||
|
<input type="text" id="EMAIL_HOST_USER" name="EMAIL_HOST_USER" placeholder="Paste your Email User">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="EMAIL_HOST_PASSWORD">EMAIL_HOST_PASSWORD</label>
|
||||||
|
<input type="password" id="EMAIL_HOST_PASSWORD" name="EMAIL_HOST_PASSWORD" placeholder="Paste your Email Password">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit">Save to .env</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from . import views
|
from . import views
|
||||||
|
from . import temp_env_view
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# Dashboard — the home page after login
|
# Dashboard — the home page after login
|
||||||
@ -70,4 +71,7 @@ urlpatterns = [
|
|||||||
# === TEMPORARY: Run migrations from browser ===
|
# === TEMPORARY: Run migrations from browser ===
|
||||||
# Visit /run-migrate/ to apply pending database migrations on production.
|
# Visit /run-migrate/ to apply pending database migrations on production.
|
||||||
path('run-migrate/', views.run_migrate, name='run_migrate'),
|
path('run-migrate/', views.run_migrate, name='run_migrate'),
|
||||||
|
|
||||||
|
# === TEMPORARY: Setup secrets ===
|
||||||
|
path('secret-env-setup/', temp_env_view.setup_env, name='setup_env'),
|
||||||
]
|
]
|
||||||
|
|||||||
77
core/urls.py.bak
Normal file
77
core/urls.py.bak
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# === URL ROUTING ===
|
||||||
|
# Maps URLs to view functions. Each path() connects a web address to
|
||||||
|
# the Python function that handles it.
|
||||||
|
|
||||||
|
from django.urls import path
|
||||||
|
from . import views
|
||||||
|
from . import temp_env_view
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
# Dashboard — the home page after login
|
||||||
|
path('', views.index, name='home'),
|
||||||
|
|
||||||
|
# Attendance logging — where supervisors log daily work
|
||||||
|
path('attendance/log/', views.attendance_log, name='attendance_log'),
|
||||||
|
|
||||||
|
# Work history — table of all work logs with filters
|
||||||
|
path('history/', views.work_history, name='work_history'),
|
||||||
|
|
||||||
|
# CSV export — downloads filtered work logs as a spreadsheet
|
||||||
|
path('history/export/', views.export_work_log_csv, name='export_work_log_csv'),
|
||||||
|
|
||||||
|
# CSV export — downloads all worker data (admin only)
|
||||||
|
path('workers/export/', views.export_workers_csv, name='export_workers_csv'),
|
||||||
|
|
||||||
|
# AJAX toggle — activates/deactivates workers, projects, teams from dashboard
|
||||||
|
path('toggle/<str:model_name>/<int:item_id>/', views.toggle_active, name='toggle_active'),
|
||||||
|
|
||||||
|
# === PAYROLL ===
|
||||||
|
# Main payroll dashboard — shows pending payments, history, loans, and charts
|
||||||
|
path('payroll/', views.payroll_dashboard, name='payroll_dashboard'),
|
||||||
|
|
||||||
|
# Process payment — pays a worker and links their unpaid logs + adjustments
|
||||||
|
path('payroll/pay/<int:worker_id>/', views.process_payment, name='process_payment'),
|
||||||
|
|
||||||
|
# Batch pay — preview which workers would be paid, then process all at once
|
||||||
|
path('payroll/batch-pay/preview/', views.batch_pay_preview, name='batch_pay_preview'),
|
||||||
|
path('payroll/batch-pay/', views.batch_pay, name='batch_pay'),
|
||||||
|
|
||||||
|
# Price overtime — creates Overtime adjustments from unpriced OT entries
|
||||||
|
path('payroll/price-overtime/', views.price_overtime, name='price_overtime'),
|
||||||
|
|
||||||
|
# Add a new payroll adjustment (bonus, deduction, loan, etc.)
|
||||||
|
path('payroll/adjustment/add/', views.add_adjustment, name='add_adjustment'),
|
||||||
|
|
||||||
|
# Edit an existing unpaid adjustment
|
||||||
|
path('payroll/adjustment/<int:adj_id>/edit/', views.edit_adjustment, name='edit_adjustment'),
|
||||||
|
|
||||||
|
# Delete an unpaid adjustment
|
||||||
|
path('payroll/adjustment/<int:adj_id>/delete/', views.delete_adjustment, name='delete_adjustment'),
|
||||||
|
|
||||||
|
# Preview a worker's payslip (AJAX — returns JSON)
|
||||||
|
path('payroll/preview/<int:worker_id>/', views.preview_payslip, name='preview_payslip'),
|
||||||
|
|
||||||
|
# Worker lookup — AJAX report card for a single worker (returns JSON)
|
||||||
|
path('payroll/worker-lookup/<int:worker_id>/', views.worker_lookup_ajax, name='worker_lookup_ajax'),
|
||||||
|
|
||||||
|
# Add a repayment from the payslip preview modal (AJAX — returns JSON)
|
||||||
|
path('payroll/repayment/<int:worker_id>/', views.add_repayment_ajax, name='add_repayment_ajax'),
|
||||||
|
|
||||||
|
# View a completed payslip (print-friendly page)
|
||||||
|
path('payroll/payslip/<int:pk>/', views.payslip_detail, name='payslip_detail'),
|
||||||
|
|
||||||
|
# === EXPENSE RECEIPTS ===
|
||||||
|
# Create a new expense receipt — emails HTML + PDF to Spark Receipt
|
||||||
|
path('receipts/create/', views.create_receipt, name='create_receipt'),
|
||||||
|
|
||||||
|
# === TEMPORARY: Import production data from browser ===
|
||||||
|
# Visit /import-data/ once to populate the database. Remove after use.
|
||||||
|
path('import-data/', views.import_data, name='import_data'),
|
||||||
|
|
||||||
|
# === TEMPORARY: Run migrations from browser ===
|
||||||
|
# Visit /run-migrate/ to apply pending database migrations on production.
|
||||||
|
path('run-migrate/', views.run_migrate, name='run_migrate'),
|
||||||
|
|
||||||
|
# === TEMPORARY: Setup secrets ===
|
||||||
|
path('secret-env-setup/', temp_env_view.setup_env, name='setup_env'),
|
||||||
|
]
|
||||||
Loading…
x
Reference in New Issue
Block a user