267 lines
9.8 KiB
Python
267 lines
9.8 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
API測試腳本
|
||
"""
|
||
|
||
import requests
|
||
import json
|
||
import sys
|
||
import time
|
||
from multiprocessing import Process
|
||
|
||
def start_flask_app():
|
||
"""在子進程中啟動Flask應用"""
|
||
try:
|
||
# 簡化的Flask應用啟動
|
||
from flask import Flask, jsonify, request, session
|
||
import pymysql
|
||
|
||
app = Flask(__name__)
|
||
app.config['SECRET_KEY'] = 'test-secret-key'
|
||
|
||
@app.route('/health')
|
||
def health():
|
||
"""健康檢查API"""
|
||
return jsonify({
|
||
'status': 'ok',
|
||
'timestamp': time.time()
|
||
})
|
||
|
||
@app.route('/api/v1/auth/login', methods=['POST'])
|
||
def login():
|
||
"""簡化的登入API"""
|
||
try:
|
||
data = request.get_json()
|
||
username = data.get('username')
|
||
password = data.get('password')
|
||
|
||
if not username or not password:
|
||
return jsonify({
|
||
'success': False,
|
||
'error': 'MISSING_CREDENTIALS',
|
||
'message': '缺少帳號或密碼'
|
||
}), 400
|
||
|
||
# 測試LDAP認證
|
||
import ldap3
|
||
from ldap3 import Server, Connection, ALL
|
||
|
||
server = Server('panjit.com.tw', port=389, get_info=ALL)
|
||
bind_dn = "CN=LdapBind,CN=Users,DC=PANJIT,DC=COM,DC=TW"
|
||
bind_password = "panjit2481"
|
||
|
||
service_conn = Connection(server, user=bind_dn, password=bind_password, auto_bind=True)
|
||
|
||
# 搜尋使用者
|
||
search_base = "OU=PANJIT,DC=panjit,DC=com,DC=tw"
|
||
search_filter = f"(userPrincipalName={username})"
|
||
|
||
result = service_conn.search(search_base, search_filter,
|
||
attributes=['displayName', 'mail', 'department', 'distinguishedName'])
|
||
|
||
if not result or not service_conn.entries:
|
||
service_conn.unbind()
|
||
return jsonify({
|
||
'success': False,
|
||
'error': 'USER_NOT_FOUND',
|
||
'message': '使用者不存在'
|
||
}), 404
|
||
|
||
user_entry = service_conn.entries[0]
|
||
user_dn = str(user_entry.distinguishedName)
|
||
|
||
# 驗證使用者密碼
|
||
user_conn = Connection(server, user=user_dn, password=password)
|
||
if not user_conn.bind():
|
||
service_conn.unbind()
|
||
return jsonify({
|
||
'success': False,
|
||
'error': 'INVALID_PASSWORD',
|
||
'message': '密碼錯誤'
|
||
}), 401
|
||
|
||
user_conn.unbind()
|
||
service_conn.unbind()
|
||
|
||
# 模擬成功登入
|
||
user_info = {
|
||
'id': 1,
|
||
'username': username.split('@')[0],
|
||
'display_name': str(user_entry.displayName) if user_entry.displayName else username,
|
||
'email': str(user_entry.mail) if user_entry.mail else username,
|
||
'department': str(user_entry.department) if user_entry.department else 'Unknown',
|
||
'is_admin': username.lower() == 'ymirliu@panjit.com.tw'
|
||
}
|
||
|
||
# 設定session
|
||
session['user_id'] = user_info['id']
|
||
session['username'] = user_info['username']
|
||
session['is_admin'] = user_info['is_admin']
|
||
|
||
return jsonify({
|
||
'success': True,
|
||
'data': {
|
||
'user': user_info
|
||
},
|
||
'message': '登入成功'
|
||
})
|
||
|
||
except Exception as e:
|
||
print(f"Login error: {e}")
|
||
return jsonify({
|
||
'success': False,
|
||
'error': 'INTERNAL_ERROR',
|
||
'message': f'系統錯誤: {str(e)}'
|
||
}), 500
|
||
|
||
@app.route('/api/v1/auth/me')
|
||
def get_current_user():
|
||
"""取得當前使用者"""
|
||
user_id = session.get('user_id')
|
||
if not user_id:
|
||
return jsonify({
|
||
'success': False,
|
||
'error': 'NOT_AUTHENTICATED',
|
||
'message': '未登入'
|
||
}), 401
|
||
|
||
return jsonify({
|
||
'success': True,
|
||
'data': {
|
||
'user': {
|
||
'id': user_id,
|
||
'username': session.get('username'),
|
||
'is_admin': session.get('is_admin', False)
|
||
}
|
||
}
|
||
})
|
||
|
||
print("Starting test Flask server on port 5000...")
|
||
app.run(host='127.0.0.1', port=5000, debug=False)
|
||
|
||
except Exception as e:
|
||
print(f"Flask app failed to start: {e}")
|
||
|
||
def test_apis():
|
||
"""測試API端點"""
|
||
base_url = 'http://127.0.0.1:5000'
|
||
|
||
# 等待Flask應用啟動
|
||
print("Waiting for Flask server to start...")
|
||
time.sleep(3)
|
||
|
||
test_results = []
|
||
|
||
# 1. 測試健康檢查
|
||
try:
|
||
response = requests.get(f'{base_url}/health', timeout=5)
|
||
if response.status_code == 200:
|
||
test_results.append(('Health Check', 'PASS'))
|
||
print("✓ Health check API works")
|
||
else:
|
||
test_results.append(('Health Check', 'FAIL'))
|
||
print(f"✗ Health check failed: {response.status_code}")
|
||
except Exception as e:
|
||
test_results.append(('Health Check', 'FAIL'))
|
||
print(f"✗ Health check failed: {e}")
|
||
|
||
# 2. 測試登入API(無效憑證)
|
||
try:
|
||
login_data = {
|
||
'username': 'invalid@panjit.com.tw',
|
||
'password': 'wrongpassword'
|
||
}
|
||
response = requests.post(f'{base_url}/api/v1/auth/login',
|
||
json=login_data, timeout=10)
|
||
|
||
if response.status_code == 404:
|
||
test_results.append(('Invalid Login', 'PASS'))
|
||
print("✓ Invalid login properly rejected")
|
||
else:
|
||
test_results.append(('Invalid Login', 'FAIL'))
|
||
print(f"✗ Invalid login test failed: {response.status_code}")
|
||
except Exception as e:
|
||
test_results.append(('Invalid Login', 'FAIL'))
|
||
print(f"✗ Invalid login test failed: {e}")
|
||
|
||
# 3. 測試登入API(有效憑證)
|
||
try:
|
||
login_data = {
|
||
'username': 'ymirliu@panjit.com.tw',
|
||
'password': 'ˇ3EDC4rfv5tgb' # 使用提供的測試密碼
|
||
}
|
||
response = requests.post(f'{base_url}/api/v1/auth/login',
|
||
json=login_data, timeout=15)
|
||
|
||
if response.status_code == 200:
|
||
result = response.json()
|
||
if result.get('success'):
|
||
test_results.append(('Valid Login', 'PASS'))
|
||
print("✓ Valid login successful")
|
||
|
||
# 保存session cookies
|
||
cookies = response.cookies
|
||
|
||
# 4. 測試取得當前使用者
|
||
try:
|
||
me_response = requests.get(f'{base_url}/api/v1/auth/me',
|
||
cookies=cookies, timeout=5)
|
||
|
||
if me_response.status_code == 200:
|
||
me_result = me_response.json()
|
||
if me_result.get('success'):
|
||
test_results.append(('Get Current User', 'PASS'))
|
||
print("✓ Get current user API works")
|
||
else:
|
||
test_results.append(('Get Current User', 'FAIL'))
|
||
else:
|
||
test_results.append(('Get Current User', 'FAIL'))
|
||
|
||
except Exception as e:
|
||
test_results.append(('Get Current User', 'FAIL'))
|
||
print(f"✗ Get current user failed: {e}")
|
||
|
||
else:
|
||
test_results.append(('Valid Login', 'FAIL'))
|
||
print(f"✗ Login failed: {result.get('message', 'Unknown error')}")
|
||
else:
|
||
test_results.append(('Valid Login', 'FAIL'))
|
||
print(f"✗ Valid login failed: {response.status_code}")
|
||
if response.headers.get('content-type', '').startswith('application/json'):
|
||
print(f"Response: {response.json()}")
|
||
|
||
except Exception as e:
|
||
test_results.append(('Valid Login', 'FAIL'))
|
||
print(f"✗ Valid login test failed: {e}")
|
||
|
||
# 輸出測試結果
|
||
print("\n=== API Test Results ===")
|
||
for test_name, result in test_results:
|
||
print(f"{test_name}: {result}")
|
||
|
||
passed = sum(1 for _, result in test_results if result == 'PASS')
|
||
total = len(test_results)
|
||
print(f"\nPassed: {passed}/{total}")
|
||
|
||
return test_results
|
||
|
||
if __name__ == '__main__':
|
||
if len(sys.argv) > 1 and sys.argv[1] == 'server':
|
||
# 只啟動服務器
|
||
start_flask_app()
|
||
else:
|
||
# 在子進程中啟動Flask應用
|
||
flask_process = Process(target=start_flask_app)
|
||
flask_process.start()
|
||
|
||
try:
|
||
# 運行測試
|
||
test_results = test_apis()
|
||
|
||
finally:
|
||
# 關閉Flask進程
|
||
flask_process.terminate()
|
||
flask_process.join(timeout=3)
|
||
if flask_process.is_alive():
|
||
flask_process.kill() |