blob: 23ff49bc3825fb3bd246c4b9531c32f59258e479 [file] [log] [blame]
Raverafc93da2025-06-15 18:12:49 +08001from flask import Blueprint, request, jsonify
2from .functions.FAuth import FAuth
3from sqlalchemy import create_engine
4from sqlalchemy.orm import sessionmaker
5from config import Config
6from functools import wraps
7from datetime import datetime
8
9main = Blueprint('main', __name__)
10
11def token_required(f):
12 """装饰器:需要令牌验证"""
13 @wraps(f)
14 def decorated(*args, **kwargs):
15 token = request.headers.get('Authorization')
16 if not token:
17 return jsonify({'success': False, 'message': '缺少访问令牌'}), 401
18
19 session = None
20 try:
21 # 移除Bearer前缀
22 if token.startswith('Bearer '):
23 token = token[7:]
24
25 engine = create_engine(Config.SQLURL)
26 SessionLocal = sessionmaker(bind=engine)
27 session = SessionLocal()
28 f_auth = FAuth(session)
29
30 user = f_auth.get_user_by_token(token)
31 if not user:
32 return jsonify({'success': False, 'message': '无效的访问令牌'}), 401
33
34 # 将用户信息传递给路由函数
35 return f(user, *args, **kwargs)
36 except Exception as e:
37 if session:
38 session.rollback()
39 return jsonify({'success': False, 'message': '令牌验证失败'}), 401
40 finally:
41 if session:
42 session.close()
43
44 return decorated
45
46@main.route('/login', methods=['POST'])
47def login():
48 """用户登录接口"""
49 session = None
50 try:
51 data = request.get_json()
52
53 # 验证必填字段
54 if not data or not data.get('email') or not data.get('password'):
55 return jsonify({
56 'success': False,
57 'message': '用户名和密码不能为空'
58 }), 400
59
60 email = data['email']
61 password = data['password']
62
63 # 创建数据库连接
64 engine = create_engine(Config.SQLURL)
65 SessionLocal = sessionmaker(bind=engine)
66 session = SessionLocal()
67
68 # 执行登录
69 f_auth = FAuth(session)
70 result = f_auth.login(email, password)
71
72 if result['success']:
73 session.commit()
74 return jsonify(result), 200
75 else:
76 return jsonify(result), 401
77
78 except Exception as e:
79 if session:
80 session.rollback()
81 return jsonify({
82 'success': False,
83 'message': '服务器内部错误'
84 }), 500
85 finally:
86 if session:
87 session.close()
88
89@main.route('/register', methods=['POST'])
90def register():
91 """用户注册接口"""
92
93 engine = create_engine(Config.SQLURL)
94 SessionLocal = sessionmaker(bind=engine)
95 session = SessionLocal()
96
97 try:
98 data = request.get_json()
99
100 # 验证必填字段
101 if not data or not data.get('username') or not data.get('email') or not data.get('password') or not data.get('verification_code'):
102 return jsonify({
103 'success': False,
104 'message': '用户名、邮箱和密码不能为空'
105 }), 400
106
107 username = data['username']
108 email = data['email']
109 password = data['password']
110 verification_code = data['verification_code']
111
112 # 简单的邮箱格式验证
113 if '@' not in email or '.' not in email:
114 return jsonify({
115 'success': False,
116 'message': '邮箱格式不正确'
117 }), 400
118
119 # 密码长度验证
120 if len(password) < 6:
121 return jsonify({
122 'success': False,
123 'message': '密码长度不能少于6位'
124 }), 400
125
126 # 执行注册
127 f_auth = FAuth(session)
128 result = f_auth.register(username, email, password, verification_code)
129
130 if result['success']:
131 session.commit()
132 return jsonify(result), 201
133 else:
134 return jsonify(result), 400
135
136 except Exception as e:
137 session.rollback()
138 return jsonify({
139 'success': False,
140 'message': '服务器内部错误'
141 }), 500
142 finally:
143 session.close()
144
145@main.route('/profile', methods=['GET'])
146@token_required
147def get_profile(current_user):
148 """获取用户信息接口(需要登录)"""
149 try:
150 return jsonify({
151 'success': True,
152 'user': current_user.to_dict()
153 }), 200
154 except Exception as e:
155 return jsonify({
156 'success': False,
157 'message': '获取用户信息失败'
158 }), 500
159
160@main.route('/logout', methods=['POST'])
161@token_required
162def logout(current_user):
163 """用户登出接口(需要登录)"""
164 try:
165 # 这里可以将令牌加入黑名单(如果需要的话)
166 return jsonify({
167 'success': True,
168 'message': '登出成功'
169 }), 200
170 except Exception as e:
171 return jsonify({
172 'success': False,
173 'message': '登出失败'
174 }), 500
175
176@main.route('/send-verification-code', methods=['POST'])
177def send_verification_code():
178 """发送邮箱验证码接口"""
179
180 engine = create_engine(Config.SQLURL)
181 SessionLocal = sessionmaker(bind=engine)
182 session = SessionLocal()
183
184 try:
185 data = request.get_json()
186
187 # 验证必填字段
188 if not data or not data.get('email'):
189 return jsonify({
190 'success': False,
191 'message': '邮箱地址不能为空'
192 }), 400
193
194 email = data['email']
195 verification_type = data.get('type', 'register') # 默认为注册验证码
196
197 # 简单的邮箱格式验证
198 if '@' not in email or '.' not in email:
199 return jsonify({
200 'success': False,
201 'message': '邮箱格式不正确'
202 }), 400
203
204 # 发送验证码
205 f_auth = FAuth(session)
206 result = f_auth.send_verification_email(email, verification_type)
207
208 if result['success']:
209 session.commit()
210 return jsonify(result), 200
211 else:
212 return jsonify(result), 400
213
214 except Exception as e:
215 session.rollback()
216 return jsonify({
217 'success': False,
218 'message': '服务器内部错误'
219 }), 500
220 finally:
221 session.close()
222
223@main.route('/reset-password', methods=['POST'])
224def reset_password():
225 """重置密码接口"""
226
227 engine = create_engine(Config.SQLURL)
228 SessionLocal = sessionmaker(bind=engine)
229 session = SessionLocal()
230
231 try:
232 data = request.get_json()
233
234 # 验证必填字段
235 if not data or not data.get('email') or not data.get('new_password') or not data.get('verification_code'):
236 return jsonify({
237 'success': False,
238 'message': '邮箱地址、新密码和验证码不能为空'
239 }), 400
240
241 email = data['email']
242 new_password = data['new_password']
243 verification_code = data['verification_code']
244
245 # 简单的邮箱格式验证
246 if '@' not in email or '.' not in email:
247 return jsonify({
248 'success': False,
249 'message': '邮箱格式不正确'
250 }), 400
251
252 # 密码长度验证
253 if len(new_password) < 6:
254 return jsonify({
255 'success': False,
256 'message': '密码长度不能少于6位'
257 }), 400
258
259 # 重置密码
260 f_auth = FAuth(session)
261 result = f_auth.reset_password_with_verification(email, new_password, verification_code)
262
263 if result['success']:
264 session.commit()
265 return jsonify(result), 200
266 else:
267 return jsonify(result), 400
268
269 except Exception as e:
270 session.rollback()
271 return jsonify({
272 'success': False,
273 'message': '服务器内部错误'
274 }), 500
275 finally:
276 session.close()
277
278@main.route('/test-jwt', methods=['POST'])
279@token_required
280def test_jwt(current_user):
281 """测试JWT令牌接口(需要登录)"""
282 try:
283 # 获取当前请求的token(从装饰器已验证的Authorization header)
284 auth_header = request.headers.get('Authorization')
285 current_token = auth_header[7:] if auth_header and auth_header.startswith('Bearer ') else None
286
287 print(f"当前用户: {current_user.username}")
288 print(f"当前用户ID: {current_user.id}")
289 print(current_user.role)
290 print(f"Token验证成功: {current_token[:20]}..." if current_token else "No token")
291
292 # 可选:检查请求体中是否有额外的token需要验证
293 data = request.get_json() or {}
294 additional_token = data.get('token')
295
296 response_data = {
297 'success': True,
298 'message': 'JWT令牌验证成功',
299 'user': current_user.to_dict(),
300 'token_info': {
301 'header_token_verified': True,
302 'token_preview': current_token[:20] + "..." if current_token else None
303 }
304 }
305
306 # 如果请求体中有额外的token,也验证一下
307 if additional_token:
308 try:
309 additional_result = FAuth.verify_token(additional_token)
310 response_data['additional_token_verification'] = additional_result
311 print(f"额外token验证结果: {additional_result}")
312 except Exception as e:
313 response_data['additional_token_verification'] = {
314 'success': False,
315 'message': f'额外token验证失败: {str(e)}'
316 }
317
318 return jsonify(response_data), 200
319
320 except Exception as e:
321 print(f"test_jwt 错误: {str(e)}")
322 return jsonify({
323 'success': False,
324 'message': f'JWT令牌验证失败: {str(e)}'
325 }), 500