188 lines
7.1 KiB
PHP
Executable File
188 lines
7.1 KiB
PHP
Executable File
<?php
|
|
namespace App\Controllers\Web;
|
|
|
|
use Db\Database;
|
|
use App\Core\WebBaseController;
|
|
use App\Core\I18n;
|
|
|
|
class AuthController extends WebBaseController {
|
|
|
|
public function loginPage() {
|
|
if ($this->isLoggedIn()) { header('Location: /'); exit; }
|
|
I18n::init();
|
|
include __DIR__ . '/../../Views/Web/login.php';
|
|
}
|
|
|
|
public function loginSubmit() {
|
|
header('Content-Type: application/json');
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
$username = trim($data['username'] ?? '');
|
|
$password = $data['password'] ?? '';
|
|
$remember = $data['remember'] ?? false;
|
|
|
|
if (empty($username) || empty($password)) {
|
|
echo json_encode(['success' => false, 'message' => 'Please fill in all fields']);
|
|
return;
|
|
}
|
|
|
|
$db = new Database();
|
|
$user = $db->get('users', '*', ['username' => $username]);
|
|
|
|
if (!$user || !password_verify($password, $user['password'])) {
|
|
echo json_encode(['success' => false, 'message' => 'Invalid username or password']);
|
|
return;
|
|
}
|
|
if (isset($user['status']) && $user['status'] == 0) {
|
|
echo json_encode(['success' => false, 'message' => 'Account disabled']);
|
|
return;
|
|
}
|
|
// 邮箱验证检查(虚拟账户跳过)
|
|
if (empty($user['is_virtual']) && isset($user['email_verified']) && !$user['email_verified']) {
|
|
echo json_encode(['success' => false, 'message' => 'Please verify your email first', 'need_verify' => true]);
|
|
return;
|
|
}
|
|
|
|
if (session_status() === PHP_SESSION_NONE) session_start();
|
|
$_SESSION['web_user_id'] = $user['id'];
|
|
$_SESSION['web_username'] = $user['username'];
|
|
$_SESSION['web_role'] = $user['role'] ?? 'user';
|
|
$_SESSION['web_last_activity'] = time();
|
|
$_SESSION['web_ip'] = $_SERVER['REMOTE_ADDR'];
|
|
$_SESSION['web_ua'] = $_SERVER['HTTP_USER_AGENT'];
|
|
if ($remember) $_SESSION['web_remember'] = true;
|
|
if (!empty($user['lang'])) $_SESSION['lang'] = $user['lang'];
|
|
|
|
echo json_encode(['success' => true, 'message' => 'Login successful', 'redirect' => '/']);
|
|
}
|
|
|
|
public function registerSubmit() {
|
|
header('Content-Type: application/json');
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
|
|
$username = trim($data['username'] ?? '');
|
|
$password = $data['password'] ?? '';
|
|
$confirmPassword = $data['confirm_password'] ?? '';
|
|
$email = trim($data['email'] ?? '');
|
|
$inviteCode = trim($data['invite_code'] ?? '');
|
|
$verifyCode = trim($data['verify_code'] ?? '');
|
|
|
|
if (empty($username) || empty($password) || empty($email)) {
|
|
echo json_encode(['success' => false, 'message' => 'Please fill in all required fields']);
|
|
return;
|
|
}
|
|
if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) {
|
|
echo json_encode(['success' => false, 'message' => 'Username: 3-20 chars, letters/numbers/underscore only']);
|
|
return;
|
|
}
|
|
if (strlen($password) < 6) {
|
|
echo json_encode(['success' => false, 'message' => 'Password must be at least 6 characters']);
|
|
return;
|
|
}
|
|
if ($password !== $confirmPassword) {
|
|
echo json_encode(['success' => false, 'message' => 'Passwords do not match']);
|
|
return;
|
|
}
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
echo json_encode(['success' => false, 'message' => 'Invalid email address']);
|
|
return;
|
|
}
|
|
|
|
$db = new Database();
|
|
|
|
// 唯一性检查
|
|
if ($db->get('users', 'id', ['username' => $username])) {
|
|
echo json_encode(['success' => false, 'message' => 'Username already exists']);
|
|
return;
|
|
}
|
|
if ($db->get('users', 'id', ['email' => $email])) {
|
|
echo json_encode(['success' => false, 'message' => 'Email already registered']);
|
|
return;
|
|
}
|
|
|
|
// 验证邮箱验证码
|
|
$ev = $db->get('email_verifications', '*', [
|
|
'email' => $email, 'code' => $verifyCode, 'used' => 0,
|
|
'expires_at[>]' => date('Y-m-d H:i:s'),
|
|
'ORDER' => ['id' => 'DESC']
|
|
]);
|
|
if (!$ev) {
|
|
echo json_encode(['success' => false, 'message' => 'Invalid or expired verification code']);
|
|
return;
|
|
}
|
|
|
|
// 处理邀请码 → 代理关联
|
|
$agentId = null;
|
|
if (!empty($inviteCode)) {
|
|
$agent = $db->get('agents', '*', ['agent_code' => $inviteCode, 'status' => 1]);
|
|
if ($agent) $agentId = $agent['id'];
|
|
}
|
|
|
|
$db->insert('users', [
|
|
'username' => $username,
|
|
'password' => password_hash($password, PASSWORD_DEFAULT),
|
|
'email' => $email,
|
|
'role' => 'user',
|
|
'status' => 1,
|
|
'email_verified' => 1,
|
|
'agent_id' => $agentId,
|
|
'lang' => 'en',
|
|
'created_at' => date('Y-m-d H:i:s'),
|
|
]);
|
|
|
|
// 标记验证码已用
|
|
$db->update('email_verifications', ['used' => 1], ['id' => $ev['id']]);
|
|
|
|
echo json_encode(['success' => true, 'message' => 'Registration successful', 'redirect' => '/login']);
|
|
}
|
|
|
|
public function sendVerifyCode() {
|
|
header('Content-Type: application/json');
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
$email = trim($data['email'] ?? '');
|
|
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
echo json_encode(['success' => false, 'message' => 'Invalid email']);
|
|
return;
|
|
}
|
|
|
|
// 频率限制: 60秒内只能发一次
|
|
$db = new Database();
|
|
$recent = $db->get('email_verifications', '*', [
|
|
'email' => $email,
|
|
'created_at[>]' => date('Y-m-d H:i:s', time() - 60),
|
|
]);
|
|
if ($recent) {
|
|
echo json_encode(['success' => false, 'message' => 'Please wait 60 seconds']);
|
|
return;
|
|
}
|
|
|
|
$code = str_pad(mt_rand(0, 999999), 6, '0', STR_PAD_LEFT);
|
|
$db->insert('email_verifications', [
|
|
'email' => $email,
|
|
'code' => $code,
|
|
'expires_at' => date('Y-m-d H:i:s', time() + 600), // 10分钟
|
|
'created_at' => date('Y-m-d H:i:s'),
|
|
]);
|
|
|
|
// 发送邮件
|
|
$subject = 'Email Verification Code';
|
|
$body = "Your verification code is: <b>$code</b><br>Valid for 10 minutes.";
|
|
$sent = \App\Core\Mailer::send($email, $subject, $body);
|
|
|
|
echo json_encode(['success' => true, 'message' => 'Verification code sent']);
|
|
}
|
|
|
|
public function logout() {
|
|
if (session_status() === PHP_SESSION_NONE) session_start();
|
|
$keys = ['web_user_id','web_username','web_role','web_last_activity','web_ip','web_ua','web_remember','lang'];
|
|
foreach ($keys as $k) unset($_SESSION[$k]);
|
|
header('Location: /login');
|
|
exit;
|
|
}
|
|
|
|
private function isLoggedIn(): bool {
|
|
if (session_status() === PHP_SESSION_NONE) session_start();
|
|
return isset($_SESSION['web_user_id']);
|
|
}
|
|
}
|