futranbg commited on
Commit
5d0ba21
·
verified ·
1 Parent(s): 660bbe4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -38
app.py CHANGED
@@ -1,6 +1,6 @@
1
  import os
2
  import json
3
- from flask import Flask, request, g, Response, render_template, redirect, url_for, flash # Thêm render_template, redirect, url_for, flash
4
  import psycopg2
5
  from dotenv import load_dotenv
6
  from werkzeug.security import generate_password_hash, check_password_hash
@@ -21,8 +21,8 @@ DB_PORT = os.getenv('DB_PORT')
21
  # Biến môi trường cho mật khẩu trang
22
  PAGE_PASSWORD = os.getenv('PAGE_PASSWORD')
23
 
24
- # Cấu hình secret key cho Flask (cần thiết cho flash messages và session)
25
- # Trong môi trường production, hãy tạo một chuỗi ngẫu nhiên mạnh và lưu vào biến môi trường
26
  app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET_KEY', 'mot_chuoi_bi_mat_rat_ngau_nhien_va_dai')
27
 
28
  if not PAGE_PASSWORD:
@@ -52,7 +52,7 @@ def close_db_connection(exception):
52
  db.close()
53
  print("Đã đóng kết nối Supabase PostgreSQL.")
54
 
55
- # --- Hàm tiện ích để trả về JSON với tiếng Việt (vẫn giữ cho các API nếu cần) ---
56
  def custom_jsonify(data, status_code=200):
57
  response = Response(
58
  response=json.dumps(data, ensure_ascii=False),
@@ -65,25 +65,58 @@ def custom_jsonify(data, status_code=200):
65
  def require_page_password(f):
66
  @wraps(f)
67
  def decorated_function(*args, **kwargs):
68
- # Kiểm tra mật khẩu trang từ form (POST) hoặc query string (GET)
69
- provided_password = request.form.get('page_password') or request.args.get('page_password')
 
70
 
71
- # Nếu POST request, không mật khẩu trong form, có thể kiểm tra header nếu muốn hỗ trợ API
 
72
  if request.method == 'POST' and not provided_password:
73
  provided_password = request.headers.get('X-Page-Password')
74
 
75
  if not PAGE_PASSWORD:
76
  flash("Lỗi cấu hình server: Mật khẩu trang chưa được thiết lập.", "error")
77
- return redirect(url_for('home')) # Chuyển hướng về trang chủ hoặc trang lỗi
78
 
79
  if provided_password == PAGE_PASSWORD:
80
- return f(*args, **kwargs)
 
 
 
81
  else:
82
  flash("Truy cập bị từ chối: Mật khẩu trang không hợp lệ.", "error")
83
- # Nếu request.referrer có, chuyển hướng về trang trước, không thì về home
84
- return redirect(request.referrer or url_for('home'))
85
  return decorated_function
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  # --- Các tuyến đường (Routes) của ứng dụng ---
88
 
89
  @app.route('/')
@@ -91,43 +124,51 @@ def home():
91
  """Trang chủ của ứng dụng."""
92
  return render_template('index.html')
93
 
94
- @app.route('/test_db', methods=['GET', 'POST'])
95
- @require_page_password
 
96
  def test_db():
97
  """Kiểm tra kết nối đến cơ sở dữ liệu và hiển thị kết quả."""
98
- if request.method == 'POST':
99
- conn = get_db_connection()
100
- if conn is None:
101
- flash("Không thể kết nối đến cơ sở dữ liệu.", "error")
102
- return render_template('test_db.html', db_version="Lỗi kết nối", status="error")
103
-
 
 
104
  try:
105
  cur = conn.cursor()
106
  cur.execute("SELECT version();")
107
  db_version = cur.fetchone()[0]
108
  cur.close()
109
  flash("Kết nối cơ sở dữ liệu thành công!", "success")
110
- return render_template('test_db.html', db_version=db_version, status="success")
 
111
  except Exception as e:
112
  flash(f"Lỗi truy vấn cơ sở dữ liệu: {e}", "error")
113
- return render_template('test_db.html', db_version="Lỗi truy vấn", status="error")
114
- return render_template('test_db.html', db_version="Chưa kiểm tra", status="none")
 
 
115
 
116
- @app.route('/create_table', methods=['GET', 'POST'])
117
- @require_page_password
118
  def create_table():
119
  """Tạo bảng 'users' nếu chưa tồn tại và hiển thị kết quả."""
120
- if request.method == 'POST':
121
- conn = get_db_connection()
122
- if conn is None:
123
- flash("Không thể kết nối đến cơ sở dữ liệu.", "error")
124
- return render_template('create_table.html', message="Lỗi kết nối", status="error")
125
-
 
 
126
  try:
127
  cur = conn.cursor()
128
  cur.execute("""
129
  CREATE TABLE IF NOT EXISTS users (
130
- id SERIAL PRIMARY KEY,
131
  name VARCHAR(100) NOT NULL,
132
  email VARCHAR(100) UNIQUE NOT NULL,
133
  password VARCHAR(255) NOT NULL
@@ -136,15 +177,18 @@ def create_table():
136
  conn.commit()
137
  cur.close()
138
  flash("Bảng 'users' đã được tạo (nếu chưa tồn tại) với cột mật khẩu.", "success")
139
- return render_template('create_table.html', message="Tạo bảng thành công", status="success")
 
140
  except Exception as e:
141
  conn.rollback()
142
  flash(f"Lỗi khi tạo bảng: {e}", "error")
143
- return render_template('create_table.html', message="Lỗi tạo bảng", status="error")
144
- return render_template('create_table.html', message="Nhấn để tạo bảng", status="none")
 
 
145
 
146
  @app.route('/add_user', methods=['GET', 'POST'])
147
- @require_page_password
148
  def add_user():
149
  """Thêm người dùng mới vào cơ sở dữ liệu với mật khẩu đã băm."""
150
  if request.method == 'POST':
@@ -184,9 +228,9 @@ def add_user():
184
  return render_template('add_user.html')
185
  return render_template('add_user.html')
186
 
187
- @app.route('/users', methods=['GET', 'POST']) # Thêm POST để xử lý form mật khẩu
188
- @require_page_password
189
- def get_users():
190
  """Lấy danh sách tất cả người dùng từ cơ sở dữ liệu."""
191
  conn = get_db_connection()
192
  users_list = []
 
1
  import os
2
  import json
3
+ from flask import Flask, request, g, Response, render_template, redirect, url_for, flash, session # Thêm 'session'
4
  import psycopg2
5
  from dotenv import load_dotenv
6
  from werkzeug.security import generate_password_hash, check_password_hash
 
21
  # Biến môi trường cho mật khẩu trang
22
  PAGE_PASSWORD = os.getenv('PAGE_PASSWORD')
23
 
24
+ # Cấu hình secret key cho Flask (CẦN THIẾT cho flash messages và session)
25
+ # Trong môi trường production, hãy tạo một chuỗi ngẫu nhiên mạnh và lưu vào biến môi trường FLASK_SECRET_KEY
26
  app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET_KEY', 'mot_chuoi_bi_mat_rat_ngau_nhien_va_dai')
27
 
28
  if not PAGE_PASSWORD:
 
52
  db.close()
53
  print("Đã đóng kết nối Supabase PostgreSQL.")
54
 
55
+ # --- Hàm tiện ích để trả về JSON với tiếng Việt (giữ cho các API nếu cần) ---
56
  def custom_jsonify(data, status_code=200):
57
  response = Response(
58
  response=json.dumps(data, ensure_ascii=False),
 
65
  def require_page_password(f):
66
  @wraps(f)
67
  def decorated_function(*args, **kwargs):
68
+ # Kiểm tra session trước
69
+ if session.get('page_logged_in'):
70
+ return f(*args, **kwargs)
71
 
72
+ # Nếu chưa đăng nhập qua session, kiểm tra mật khẩu từ form/query/header
73
+ provided_password = request.form.get('page_password') or request.args.get('page_password')
74
  if request.method == 'POST' and not provided_password:
75
  provided_password = request.headers.get('X-Page-Password')
76
 
77
  if not PAGE_PASSWORD:
78
  flash("Lỗi cấu hình server: Mật khẩu trang chưa được thiết lập.", "error")
79
+ return redirect(url_for('home'))
80
 
81
  if provided_password == PAGE_PASSWORD:
82
+ session['page_logged_in'] = True # Đặt session là đã đăng nhập
83
+ # Để tránh lỗi chuyển hướng lại chính trang đó với POST,
84
+ # hãy chuyển hướng đến chính URL hiện tại nhưng là GET request
85
+ return redirect(request.url)
86
  else:
87
  flash("Truy cập bị từ chối: Mật khẩu trang không hợp lệ.", "error")
88
+ return render_template('page_password_form.html', next_url=request.url) # Hiển thị form mật khẩu riêng
 
89
  return decorated_function
90
 
91
+ # --- Tuyến đường mới để hiển thị form mật khẩu trang và xử lý đăng nhập ---
92
+ @app.route('/page_password', methods=['GET', 'POST'])
93
+ def page_password_form():
94
+ next_url = request.args.get('next') or url_for('home') # Lấy URL gốc muốn truy cập sau khi nhập mật khẩu
95
+
96
+ if request.method == 'POST':
97
+ provided_password = request.form.get('page_password_input') # Lấy từ form riêng này
98
+
99
+ if not PAGE_PASSWORD:
100
+ flash("Lỗi cấu hình server: Mật khẩu trang chưa được thiết lập.", "error")
101
+ return redirect(url_for('home'))
102
+
103
+ if provided_password == PAGE_PASSWORD:
104
+ session['page_logged_in'] = True
105
+ flash("Mật khẩu trang đã được xác thực thành công!", "success")
106
+ return redirect(next_url)
107
+ else:
108
+ flash("Mật khẩu trang không hợp lệ. Vui lòng thử lại.", "error")
109
+ return render_template('page_password_form.html', next_url=next_url)
110
+
111
+ # Nếu là GET request, hiển thị form mật khẩu
112
+ return render_template('page_password_form.html', next_url=next_url)
113
+
114
+ @app.route('/page_logout')
115
+ def page_logout():
116
+ session.pop('page_logged_in', None)
117
+ flash("Bạn đã đăng xuất khỏi phiên mật khẩu trang.", "info")
118
+ return redirect(url_for('home'))
119
+
120
  # --- Các tuyến đường (Routes) của ứng dụng ---
121
 
122
  @app.route('/')
 
124
  """Trang chủ của ứng dụng."""
125
  return render_template('index.html')
126
 
127
+ # Áp dụng decorator cho các trang cần bảo vệ
128
+ @app.route('/test_db', methods=['GET']) # Đổi thành GET
129
+ @require_page_password # Áp dụng bảo vệ
130
  def test_db():
131
  """Kiểm tra kết nối đến cơ sở dữ liệu và hiển thị kết quả."""
132
+ conn = get_db_connection()
133
+ db_version_info = "Chưa kiểm tra"
134
+ status_info = "none"
135
+ if conn is None:
136
+ flash("Không thể kết nối đến cơ sở dữ liệu.", "error")
137
+ db_version_info = "Lỗi kết nối"
138
+ status_info = "error"
139
+ else:
140
  try:
141
  cur = conn.cursor()
142
  cur.execute("SELECT version();")
143
  db_version = cur.fetchone()[0]
144
  cur.close()
145
  flash("Kết nối cơ sở dữ liệu thành công!", "success")
146
+ db_version_info = db_version
147
+ status_info = "success"
148
  except Exception as e:
149
  flash(f"Lỗi truy vấn cơ sở dữ liệu: {e}", "error")
150
+ db_version_info = "Lỗi truy vấn"
151
+ status_info = "error"
152
+ return render_template('test_db.html', db_version=db_version_info, status=status_info)
153
+
154
 
155
+ @app.route('/create_table', methods=['GET']) # Đổi thành GET
156
+ @require_page_password # Áp dụng bảo vệ
157
  def create_table():
158
  """Tạo bảng 'users' nếu chưa tồn tại và hiển thị kết quả."""
159
+ conn = get_db_connection()
160
+ message_info = "Chưa tạo"
161
+ status_info = "none"
162
+ if conn is None:
163
+ flash("Không thể kết nối đến cơ sở dữ liệu.", "error")
164
+ message_info = "Lỗi kết nối"
165
+ status_info = "error"
166
+ else:
167
  try:
168
  cur = conn.cursor()
169
  cur.execute("""
170
  CREATE TABLE IF NOT EXISTS users (
171
+ id SERIAL PRIMARY음을 PRIMARY KEY,
172
  name VARCHAR(100) NOT NULL,
173
  email VARCHAR(100) UNIQUE NOT NULL,
174
  password VARCHAR(255) NOT NULL
 
177
  conn.commit()
178
  cur.close()
179
  flash("Bảng 'users' đã được tạo (nếu chưa tồn tại) với cột mật khẩu.", "success")
180
+ message_info = "Tạo bảng thành công"
181
+ status_info = "success"
182
  except Exception as e:
183
  conn.rollback()
184
  flash(f"Lỗi khi tạo bảng: {e}", "error")
185
+ message_info = "Lỗi tạo bảng"
186
+ status_info = "error"
187
+ return render_template('create_table.html', message=message_info, status=status_info)
188
+
189
 
190
  @app.route('/add_user', methods=['GET', 'POST'])
191
+ @require_page_password # Áp dụng bảo vệ
192
  def add_user():
193
  """Thêm người dùng mới vào cơ sở dữ liệu với mật khẩu đã băm."""
194
  if request.method == 'POST':
 
228
  return render_template('add_user.html')
229
  return render_template('add_user.html')
230
 
231
+ @app.route('/get_users', methods=['GET']) # Đổi thành GET
232
+ @require_page_password # Áp dụng bảo vệ
233
+ def get_users(): # Đổi tên hàm thành get_users cho rõ ràng
234
  """Lấy danh sách tất cả người dùng từ cơ sở dữ liệu."""
235
  conn = get_db_connection()
236
  users_list = []