-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapp.py
More file actions
215 lines (176 loc) · 7.07 KB
/
app.py
File metadata and controls
215 lines (176 loc) · 7.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
from flask import Flask, render_template, request, flash, redirect, url_for, jsonify, make_response
import csv
import io
import os
from functools import wraps
import base64
from dotenv import load_dotenv
from database import init_database, save_donation, get_all_donations, get_donation_stats, backup_donations_to_json
# test
# Load environment variables from .env file
load_dotenv()
app = Flask(__name__)
# Use environment variables for security
app.secret_key = os.getenv('FLASK_SECRET_KEY', 'ai-world-leaders-fallback-key')
# Get PayPal Client ID from environment
PAYPAL_CLIENT_ID = os.getenv('PAYPAL_CLIENT_ID', '')
# Admin credentials from environment variables
ADMIN_USERNAME = os.getenv('ADMIN_USERNAME', 'admin')
ADMIN_PASSWORD = os.getenv('ADMIN_PASSWORD', 'aiworldleaders2024')
# Initialize database on startup
init_database()
def check_auth(username, password):
"""Check if a username/password combination is valid."""
return username == ADMIN_USERNAME and password == ADMIN_PASSWORD
def authenticate():
"""Send a 401 response that enables basic auth"""
return make_response(
'Authentication required. Please enter your admin credentials.',
401,
{'WWW-Authenticate': 'Basic realm="Admin Area"'}
)
def requires_auth(f):
"""Decorator that requires HTTP Basic Authentication"""
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
@app.route('/')
def home():
return render_template('home.html')
@app.route('/about')
def about():
return render_template('about.html')
@app.route('/donate')
def donate():
return render_template('donate.html', paypal_client_id=PAYPAL_CLIENT_ID)
@app.route('/contact', methods=['GET', 'POST'])
def contact():
if request.method == 'POST':
name = request.form.get('name')
email = request.form.get('email')
message = request.form.get('message')
# Here you would typically save to database or send email
flash('Thank you for your message! We will get back to you soon.', 'success')
return redirect(url_for('contact'))
return render_template('contact.html')
@app.route('/privacy-policy')
def privacy_policy():
from datetime import datetime
return render_template('privacy_policy.html', current_date=datetime.now().strftime('%B %d, %Y'))
@app.route('/refund-policy')
def refund_policy():
return render_template('refund_policy.html')
@app.route('/thank-you')
def thank_you():
donation_amount = request.args.get('amount', None)
return render_template('thank_you.html', donation_amount=donation_amount)
@app.route('/health')
def health_check():
"""Health check endpoint for Railway"""
try:
from database import test_database_connection
db_ok, db_msg = test_database_connection()
return jsonify({
'status': 'healthy' if db_ok else 'partial',
'database': db_msg,
'environment_vars': {
'DATABASE_URL': 'present' if os.getenv('DATABASE_URL') else 'missing',
'PAYPAL_CLIENT_ID': 'present' if PAYPAL_CLIENT_ID else 'missing'
}
}), 200 if db_ok else 503
except Exception as e:
return jsonify({
'status': 'error',
'message': str(e)
}), 500
@app.route('/donation-success', methods=['POST'])
def donation_success():
try:
data = request.get_json()
paypal_details = data.get('paypal_details', {})
donor_info = data.get('donor_info', {})
# Prepare donation data for database
donation_data = {
'first_name': donor_info.get('firstName', ''),
'last_name': donor_info.get('lastName', ''),
'email': donor_info.get('email', ''),
'message': donor_info.get('message', ''),
'amount': float(data.get('amount', 0)),
'transaction_id': paypal_details.get('id', ''),
'payer_email': paypal_details.get('payer', {}).get('email_address', ''),
'donation_type': 'oneTime' # Can be extended for recurring
}
# Save to database
donation_id = save_donation(donation_data)
if donation_id:
print(f"Donation saved: ${donation_data['amount']:.2f} from {donation_data['first_name']} {donation_data['last_name']}")
return jsonify({'status': 'success', 'message': 'Donation recorded successfully', 'donation_id': donation_id})
else:
return jsonify({'status': 'warning', 'message': 'Donation processed but may be duplicate'})
except Exception as e:
print(f"Error processing donation: {str(e)}")
return jsonify({'status': 'error', 'message': 'Failed to record donation'}), 500
@app.route('/admin/donations')
@requires_auth
def admin_donations():
"""Admin page to view all donations"""
donations = get_all_donations()
stats = get_donation_stats()
return render_template('admin_donations.html', donations=donations, stats=stats)
@app.route('/admin/donations/export')
@requires_auth
def export_donations():
"""Export donations to CSV"""
donations = get_all_donations()
# Create CSV in memory
output = io.StringIO()
writer = csv.writer(output)
# Write header
writer.writerow(['ID', 'First Name', 'Last Name', 'Email', 'Amount', 'Message', 'PayPal Transaction ID', 'PayPal Email', 'Date'])
# Write data
for donation in donations:
writer.writerow([
donation['id'],
donation['first_name'],
donation['last_name'],
donation['email'],
f"${donation['amount']:.2f}",
donation['message'],
donation['paypal_transaction_id'],
donation['paypal_payer_email'],
donation['created_at']
])
# Create response
response = make_response(output.getvalue())
response.headers['Content-Type'] = 'text/csv'
response.headers['Content-Disposition'] = 'attachment; filename=donations_export.csv'
return response
@app.route('/admin/donations/backup')
@requires_auth
def backup_donations():
"""Create JSON backup of donations"""
filename = backup_donations_to_json()
if filename:
flash(f'Backup created successfully: {filename}', 'success')
else:
flash('Failed to create backup', 'error')
return redirect(url_for('admin_donations'))
# ---------- NEW: Summer Class 2025 pages ----------
@app.route('/summer-2025')
def summer_2025():
"""Public page showcasing the Summer Class 2025 program."""
return render_template('summer_2025.html')
# Optional convenience redirects (useful if links vary)
@app.route('/summer')
def summer_redirect():
return redirect(url_for('summer_2025'), code=302)
@app.route('/summer-classes')
def summer_classes_redirect():
return redirect(url_for('summer_2025'), code=302)
# --------------------------------------------------
if __name__ == '__main__':
app.run(debug=True)