diff --git a/core/temp_env_view.py b/core/temp_env_view.py new file mode 100644 index 0000000..12875e5 --- /dev/null +++ b/core/temp_env_view.py @@ -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("

Success! Secrets safely appended to .env.

Please return to the AI chat, ask me to restart the app, and then I will delete this temporary page.

") + + return render(request, "core/temp_env_setup.html") diff --git a/core/templates/core/temp_env_setup.html b/core/templates/core/temp_env_setup.html new file mode 100644 index 0000000..f457f66 --- /dev/null +++ b/core/templates/core/temp_env_setup.html @@ -0,0 +1,45 @@ + + + + + + Secure Environment Setup + + + +

Secure Environment Setup

+

Warning: This page is temporary and should be deleted immediately after you save your secrets. Only administrators can view this page.

+ +
+ {% csrf_token %} +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ + \ No newline at end of file diff --git a/core/urls.py b/core/urls.py index 9d4020c..5343772 100644 --- a/core/urls.py +++ b/core/urls.py @@ -4,6 +4,7 @@ from django.urls import path from . import views +from . import temp_env_view urlpatterns = [ # Dashboard — the home page after login @@ -70,4 +71,7 @@ urlpatterns = [ # === 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'), ] diff --git a/core/urls.py.bak b/core/urls.py.bak new file mode 100644 index 0000000..5343772 --- /dev/null +++ b/core/urls.py.bak @@ -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///', 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//', 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//edit/', views.edit_adjustment, name='edit_adjustment'), + + # Delete an unpaid adjustment + path('payroll/adjustment//delete/', views.delete_adjustment, name='delete_adjustment'), + + # Preview a worker's payslip (AJAX — returns JSON) + path('payroll/preview//', views.preview_payslip, name='preview_payslip'), + + # Worker lookup — AJAX report card for a single worker (returns JSON) + path('payroll/worker-lookup//', views.worker_lookup_ajax, name='worker_lookup_ajax'), + + # Add a repayment from the payslip preview modal (AJAX — returns JSON) + path('payroll/repayment//', views.add_repayment_ajax, name='add_repayment_ajax'), + + # View a completed payslip (print-friendly page) + path('payroll/payslip//', 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'), +]