mirror of
https://github.com/zhinianboke/xianyu-auto-reply.git
synced 2025-08-30 01:27:35 +08:00
添加是否开启注册开关
This commit is contained in:
parent
a87f1904c0
commit
d53a114dba
@ -342,7 +342,8 @@ class DBManager:
|
||||
# 插入默认系统设置(不包括管理员密码,由reply_server.py初始化)
|
||||
cursor.execute('''
|
||||
INSERT OR IGNORE INTO system_settings (key, value, description) VALUES
|
||||
('theme_color', 'blue', '主题颜色')
|
||||
('theme_color', 'blue', '主题颜色'),
|
||||
('registration_enabled', 'true', '是否开启用户注册')
|
||||
''')
|
||||
|
||||
# 检查并升级数据库
|
||||
|
113
reply_server.py
113
reply_server.py
@ -85,6 +85,8 @@ class LoginResponse(BaseModel):
|
||||
token: Optional[str] = None
|
||||
message: str
|
||||
user_id: Optional[int] = None
|
||||
username: Optional[str] = None
|
||||
is_admin: Optional[bool] = None
|
||||
|
||||
|
||||
class ChangePasswordRequest(BaseModel):
|
||||
@ -397,6 +399,33 @@ async def login_page():
|
||||
# 注册页面路由
|
||||
@app.get('/register.html', response_class=HTMLResponse)
|
||||
async def register_page():
|
||||
# 检查注册是否开启
|
||||
from db_manager import db_manager
|
||||
registration_enabled = db_manager.get_system_setting('registration_enabled')
|
||||
if registration_enabled != 'true':
|
||||
return HTMLResponse('''
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>注册已关闭</title>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
|
||||
.message { color: #666; font-size: 18px; }
|
||||
.back-link { margin-top: 20px; }
|
||||
.back-link a { color: #007bff; text-decoration: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>🚫 注册功能已关闭</h2>
|
||||
<p class="message">系统管理员已关闭用户注册功能</p>
|
||||
<div class="back-link">
|
||||
<a href="/">← 返回首页</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
''', status_code=403)
|
||||
|
||||
register_path = os.path.join(static_dir, 'register.html')
|
||||
if os.path.exists(register_path):
|
||||
with open(register_path, 'r', encoding='utf-8') as f:
|
||||
@ -491,7 +520,9 @@ async def login(request: LoginRequest):
|
||||
success=True,
|
||||
token=token,
|
||||
message="登录成功",
|
||||
user_id=user['id']
|
||||
user_id=user['id'],
|
||||
username=user['username'],
|
||||
is_admin=(user['username'] == ADMIN_USERNAME)
|
||||
)
|
||||
|
||||
logger.warning(f"【{request.username}】登录失败:用户名或密码错误")
|
||||
@ -520,7 +551,9 @@ async def login(request: LoginRequest):
|
||||
success=True,
|
||||
token=token,
|
||||
message="登录成功",
|
||||
user_id=user['id']
|
||||
user_id=user['id'],
|
||||
username=user['username'],
|
||||
is_admin=(user['username'] == ADMIN_USERNAME)
|
||||
)
|
||||
|
||||
logger.warning(f"【{request.email}】邮箱登录失败:邮箱或密码错误")
|
||||
@ -564,7 +597,9 @@ async def login(request: LoginRequest):
|
||||
success=True,
|
||||
token=token,
|
||||
message="登录成功",
|
||||
user_id=user['id']
|
||||
user_id=user['id'],
|
||||
username=user['username'],
|
||||
is_admin=(user['username'] == ADMIN_USERNAME)
|
||||
)
|
||||
|
||||
else:
|
||||
@ -581,7 +616,8 @@ async def verify(user_info: Optional[Dict[str, Any]] = Depends(verify_token)):
|
||||
return {
|
||||
"authenticated": True,
|
||||
"user_id": user_info['user_id'],
|
||||
"username": user_info['username']
|
||||
"username": user_info['username'],
|
||||
"is_admin": user_info['username'] == ADMIN_USERNAME
|
||||
}
|
||||
return {"authenticated": False}
|
||||
|
||||
@ -759,6 +795,15 @@ async def send_verification_code(request: SendCodeRequest):
|
||||
async def register(request: RegisterRequest):
|
||||
from db_manager import db_manager
|
||||
|
||||
# 检查注册是否开启
|
||||
registration_enabled = db_manager.get_system_setting('registration_enabled')
|
||||
if registration_enabled != 'true':
|
||||
logger.warning(f"【{request.username}】注册失败: 注册功能已关闭")
|
||||
return RegisterResponse(
|
||||
success=False,
|
||||
message="注册功能已关闭,请联系管理员"
|
||||
)
|
||||
|
||||
try:
|
||||
logger.info(f"【{request.username}】尝试注册,邮箱: {request.email}")
|
||||
|
||||
@ -1420,6 +1465,66 @@ def update_system_setting(key: str, setting_data: SystemSettingIn, _: None = Dep
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
# ------------------------- 注册设置接口 -------------------------
|
||||
|
||||
@app.get('/registration-status')
|
||||
def get_registration_status():
|
||||
"""获取注册开关状态(公开接口,无需认证)"""
|
||||
from db_manager import db_manager
|
||||
try:
|
||||
enabled_str = db_manager.get_system_setting('registration_enabled')
|
||||
logger.info(f"从数据库获取的注册设置值: '{enabled_str}'") # 调试信息
|
||||
|
||||
# 如果设置不存在,默认为开启
|
||||
if enabled_str is None:
|
||||
enabled_bool = True
|
||||
message = '注册功能已开启'
|
||||
else:
|
||||
enabled_bool = enabled_str == 'true'
|
||||
message = '注册功能已开启' if enabled_bool else '注册功能已关闭'
|
||||
|
||||
logger.info(f"解析后的注册状态: enabled={enabled_bool}, message='{message}'") # 调试信息
|
||||
|
||||
return {
|
||||
'enabled': enabled_bool,
|
||||
'message': message
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"获取注册状态失败: {e}")
|
||||
return {'enabled': True, 'message': '注册功能已开启'} # 出错时默认开启
|
||||
|
||||
|
||||
class RegistrationSettingUpdate(BaseModel):
|
||||
enabled: bool
|
||||
|
||||
|
||||
@app.put('/registration-settings')
|
||||
def update_registration_settings(setting_data: RegistrationSettingUpdate, admin_user: Dict[str, Any] = Depends(require_admin)):
|
||||
"""更新注册开关设置(仅管理员)"""
|
||||
from db_manager import db_manager
|
||||
try:
|
||||
enabled = setting_data.enabled
|
||||
success = db_manager.set_system_setting(
|
||||
'registration_enabled',
|
||||
'true' if enabled else 'false',
|
||||
'是否开启用户注册'
|
||||
)
|
||||
if success:
|
||||
log_with_user('info', f"更新注册设置: {'开启' if enabled else '关闭'}", admin_user)
|
||||
return {
|
||||
'success': True,
|
||||
'enabled': enabled,
|
||||
'message': f"注册功能已{'开启' if enabled else '关闭'}"
|
||||
}
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail='更新注册设置失败')
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"更新注册设置失败: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -983,6 +983,41 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 注册设置 (仅管理员可见) -->
|
||||
<div id="registration-settings" class="row mt-4" style="display: none;">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<i class="bi bi-person-plus me-2"></i>注册设置
|
||||
<span class="badge bg-warning ms-2">管理员专用</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="registrationEnabled">
|
||||
<label class="form-check-label" for="registrationEnabled">
|
||||
<strong>开启用户注册</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-text">
|
||||
<i class="bi bi-info-circle me-1"></i>
|
||||
关闭后,新用户将无法注册账号,登录页面也不会显示注册链接
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary" onclick="updateRegistrationSettings()">
|
||||
<i class="bi bi-check-circle me-1"></i>保存设置
|
||||
</button>
|
||||
<div id="registrationStatus" class="mt-3" style="display: none;">
|
||||
<div class="alert alert-info mb-0">
|
||||
<i class="bi bi-info-circle me-2"></i>
|
||||
<span id="registrationStatusText"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 备份管理 (仅管理员可见) -->
|
||||
<div id="backup-management" class="row mt-4" style="display: none;">
|
||||
<div class="col-12">
|
||||
|
113
static/js/app.js
113
static/js/app.js
@ -76,6 +76,9 @@ function showSection(sectionName) {
|
||||
case 'message-notifications': // 【消息通知菜单】
|
||||
loadMessageNotifications();
|
||||
break;
|
||||
case 'system-settings': // 【系统设置菜单】
|
||||
loadSystemSettings();
|
||||
break;
|
||||
case 'logs': // 【日志管理菜单】
|
||||
// 如果没有日志数据,则加载
|
||||
setTimeout(() => {
|
||||
@ -1649,7 +1652,7 @@ async function checkAuth() {
|
||||
}
|
||||
|
||||
// 检查是否为管理员,显示管理员菜单和功能
|
||||
if (result.username === 'admin') {
|
||||
if (result.is_admin === true) {
|
||||
const adminMenuSection = document.getElementById('adminMenuSection');
|
||||
if (adminMenuSection) {
|
||||
adminMenuSection.style.display = 'block';
|
||||
@ -1660,6 +1663,12 @@ async function checkAuth() {
|
||||
if (backupManagement) {
|
||||
backupManagement.style.display = 'block';
|
||||
}
|
||||
|
||||
// 显示注册设置功能
|
||||
const registrationSettings = document.getElementById('registration-settings');
|
||||
if (registrationSettings) {
|
||||
registrationSettings.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -6473,3 +6482,105 @@ function editRemark(cookieId, currentRemark) {
|
||||
input.focus();
|
||||
input.select();
|
||||
}
|
||||
|
||||
// ==================== 系统设置功能 ====================
|
||||
|
||||
// 加载系统设置
|
||||
async function loadSystemSettings() {
|
||||
console.log('加载系统设置');
|
||||
|
||||
// 通过验证接口获取用户信息(更可靠)
|
||||
try {
|
||||
const response = await fetch(`${apiBase}/verify`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authToken}`
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
const isAdmin = result.is_admin === true;
|
||||
|
||||
console.log('用户信息:', result, '是否管理员:', isAdmin);
|
||||
|
||||
// 显示/隐藏注册设置(仅管理员可见)
|
||||
const registrationSettings = document.getElementById('registration-settings');
|
||||
if (registrationSettings) {
|
||||
registrationSettings.style.display = isAdmin ? 'block' : 'none';
|
||||
}
|
||||
|
||||
// 如果是管理员,加载注册设置
|
||||
if (isAdmin) {
|
||||
await loadRegistrationSettings();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error);
|
||||
// 出错时隐藏管理员功能
|
||||
const registrationSettings = document.getElementById('registration-settings');
|
||||
if (registrationSettings) {
|
||||
registrationSettings.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 加载注册设置
|
||||
async function loadRegistrationSettings() {
|
||||
try {
|
||||
const response = await fetch('/registration-status');
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
const checkbox = document.getElementById('registrationEnabled');
|
||||
if (checkbox) {
|
||||
checkbox.checked = data.enabled;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载注册设置失败:', error);
|
||||
showToast('加载注册设置失败', 'danger');
|
||||
}
|
||||
}
|
||||
|
||||
// 更新注册设置
|
||||
async function updateRegistrationSettings() {
|
||||
const checkbox = document.getElementById('registrationEnabled');
|
||||
const statusDiv = document.getElementById('registrationStatus');
|
||||
const statusText = document.getElementById('registrationStatusText');
|
||||
|
||||
if (!checkbox) return;
|
||||
|
||||
const enabled = checkbox.checked;
|
||||
|
||||
try {
|
||||
const response = await fetch('/registration-settings', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${authToken}`
|
||||
},
|
||||
body: JSON.stringify({ enabled: enabled })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
showToast(data.message, 'success');
|
||||
|
||||
// 显示状态信息
|
||||
if (statusDiv && statusText) {
|
||||
statusText.textContent = data.message;
|
||||
statusDiv.style.display = 'block';
|
||||
|
||||
// 3秒后隐藏状态信息
|
||||
setTimeout(() => {
|
||||
statusDiv.style.display = 'none';
|
||||
}, 3000);
|
||||
}
|
||||
} else {
|
||||
const errorData = await response.json();
|
||||
showToast(`更新失败: ${errorData.detail || '未知错误'}`, 'danger');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新注册设置失败:', error);
|
||||
showToast('更新注册设置失败', 'danger');
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +218,7 @@
|
||||
</form>
|
||||
|
||||
<!-- 注册链接 -->
|
||||
<div class="text-center mt-3">
|
||||
<div id="registerSection" class="text-center mt-3">
|
||||
<span class="text-muted">还没有账号?</span>
|
||||
<a href="/register.html" class="text-decoration-none">
|
||||
<i class="bi bi-person-plus me-1"></i>立即注册
|
||||
@ -377,6 +377,14 @@
|
||||
// 保存token到localStorage
|
||||
localStorage.setItem('auth_token', result.token);
|
||||
|
||||
// 保存用户信息到localStorage
|
||||
const userInfo = {
|
||||
user_id: result.user_id,
|
||||
username: result.username,
|
||||
is_admin: result.is_admin
|
||||
};
|
||||
localStorage.setItem('user_info', JSON.stringify(userInfo));
|
||||
|
||||
// 检查是否有重定向URL
|
||||
const redirectUrl = localStorage.getItem('redirectAfterLogin');
|
||||
if (redirectUrl) {
|
||||
@ -634,8 +642,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 检查注册状态
|
||||
async function checkRegistrationStatus() {
|
||||
try {
|
||||
const response = await fetch('/registration-status');
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
const registerSection = document.getElementById('registerSection');
|
||||
if (registerSection) {
|
||||
registerSection.style.display = data.enabled ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('检查注册状态失败:', error);
|
||||
// 出错时默认显示注册链接
|
||||
}
|
||||
}
|
||||
|
||||
// 事件监听器
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 检查注册状态
|
||||
checkRegistrationStatus();
|
||||
|
||||
// 登录方式切换
|
||||
document.querySelectorAll('input[name="loginType"]').forEach(radio => {
|
||||
radio.addEventListener('change', switchLoginType);
|
||||
|
Loading…
x
Reference in New Issue
Block a user