better-staridc-MNBT
1<?php
2/**
3 * user_info 插件 - 主入口
4 *
5 * 功能:注册、登录、个人信息、修改密码
6 * 架构:独立用户表 MN_plugin_user,独立认证 cookie account_token
7 * 通过 P2 通用路由注册 /account/* 路径,不依赖核心 user/plugin.php
8 */
9
10if (!defined('IN_CRONLITE')) {
11 exit;
12}
13
14require_once __DIR__ . '/lib/auth.php';
15
16mnbt_plugin_register('user_info', [
17 'name' => '用户信息',
18 'description' => '独立用户系统:注册、登录、个人信息、修改密码',
19]);
20
21/* ============================================================
22 * 页面路由
23 * ============================================================ */
24
25// 控制面板(要求登录)
26mnbt_register_route('GET', '/account', function ($params, $ctx) {
27 user_info_render('dashboard', ['page_title' => '控制面板']);
28}, 10, function () { return (bool)user_info_auth_current(); });
29
30// 登录页
31mnbt_register_route('GET', '/account/login', function ($params, $ctx) {
32 $user = user_info_auth_current();
33 if ($user) {
34 header('Location: ' . user_info_url('account'));
35 exit;
36 }
37 user_info_render('login', ['page_title' => '登录']);
38});
39
40// 注册页
41mnbt_register_route('GET', '/account/register', function ($params, $ctx) {
42 $user = user_info_auth_current();
43 if ($user) {
44 header('Location: ' . user_info_url('account'));
45 exit;
46 }
47 user_info_render('register', ['page_title' => '注册']);
48});
49
50// 退出
51mnbt_register_route('GET', '/account/logout', function ($params, $ctx) {
52 user_info_auth_logout();
53 header('Location: ' . user_info_url('account/login'));
54 exit;
55});
56
57// 个人信息页(要求登录)
58mnbt_register_route('GET', '/account/profile', function ($params, $ctx) {
59 user_info_render('profile', ['page_title' => '个人信息']);
60}, 10, function () { return (bool)user_info_auth_current(); });
61
62// 修改密码页(要求登录)
63mnbt_register_route('GET', '/account/password', function ($params, $ctx) {
64 user_info_render('password', ['page_title' => '修改密码']);
65}, 10, function () { return (bool)user_info_auth_current(); });
66
67/* ============================================================
68 * API 路由
69 * ============================================================ */
70
71// 获取当前用户信息(登录态探测 + 资料展示)
72mnbt_register_route('GET', '/account/api/me', function ($params, $ctx) {
73 $user = user_info_auth_current();
74 if (!$user) {
75 user_info_json('not_login', ['logged_in' => false]);
76 return;
77 }
78 user_info_json('ok', [
79 'logged_in' => true,
80 'user' => [
81 'id' => (int)$user['id'],
82 'username' => (string)$user['username'],
83 'email' => (string)($user['email'] ?? ''),
84 'qq' => (string)($user['qq'] ?? ''),
85 'status' => (int)($user['status'] ?? 1),
86 'created_at' => (string)($user['created_at'] ?? ''),
87 ],
88 ]);
89});
90
91// 登录 API
92mnbt_register_route('POST', '/account/api/login', function ($params, $ctx) {
93 global $DB;
94 $username = trim($_POST['username'] ?? '');
95 $password = $_POST['password'] ?? '';
96
97 if ($username === '' || $password === '') {
98 user_info_json('用户名和密码不能为空');
99 }
100 if (preg_match('/["\'\/\\\\]/', $username)) {
101 user_info_json('用户名包含非法字符');
102 }
103
104 $user = $DB->get_row_prepare("SELECT * FROM MN_plugin_user WHERE username=? LIMIT 1", [$username]);
105 if (!$user) {
106 user_info_json('用户不存在或密码错误');
107 }
108 if ((int)$user['status'] !== 1) {
109 user_info_json('账号已被禁用');
110 }
111 if (!password_verify($password, $user['password_hash'])) {
112 user_info_json('用户不存在或密码错误');
113 }
114
115 user_info_auth_login($user['id'], $user['password_hash']);
116 user_info_json('ok', ['message' => '登录成功', 'redirect' => user_info_url('account')]);
117});
118
119// 注册 API
120mnbt_register_route('POST', '/account/api/register', function ($params, $ctx) {
121 global $DB, $date;
122 $username = trim($_POST['username'] ?? '');
123 $password = $_POST['password'] ?? '';
124 $password2 = $_POST['password2'] ?? '';
125 $email = trim($_POST['email'] ?? '');
126 $qq = trim($_POST['qq'] ?? '');
127
128 // 用户名:3~32 字符,字母数字下划线
129 if (!preg_match('/^[a-zA-Z0-9_]{3,32}$/', $username)) {
130 user_info_json('用户名为 3~32 位字母、数字或下划线');
131 }
132 // 密码:至少 6 字符
133 if (strlen($password) < 6) {
134 user_info_json('密码至少 6 个字符');
135 }
136 if ($password !== $password2) {
137 user_info_json('两次输入的密码不一致');
138 }
139 // 邮箱(可选)
140 if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
141 user_info_json('邮箱格式不正确');
142 }
143 if ($email !== '' && strlen($email) > 128) {
144 user_info_json('邮箱过长');
145 }
146 // QQ(可选)
147 if ($qq !== '' && !preg_match('/^[0-9]{5,12}$/', $qq)) {
148 user_info_json('QQ 号格式不正确');
149 }
150
151 // 检查用户名唯一
152 $exists = $DB->get_row_prepare("SELECT id FROM MN_plugin_user WHERE username=? LIMIT 1", [$username]);
153 if ($exists) {
154 user_info_json('用户名已被占用');
155 }
156
157 $hash = password_hash($password, PASSWORD_BCRYPT);
158 $now = $date ?: date('Y-m-d H:i:s');
159 $ok = $DB->query_prepare(
160 "INSERT INTO MN_plugin_user (username, password_hash, email, qq, status, created_at, updated_at) VALUES (?,?,?,?,1,?,?)",
161 [$username, $hash, $email, $qq, $now, $now]
162 );
163 if (!$ok) {
164 user_info_json('注册失败,请稍后重试');
165 }
166
167 // 取自增 ID(兼容 MySQLi / SQLite)
168 $new_row = $DB->get_row_prepare("SELECT id FROM MN_plugin_user WHERE username=? LIMIT 1", [$username]);
169 $new_id = $new_row ? (int)$new_row['id'] : 0;
170 user_info_auth_login($new_id, $hash);
171 user_info_json('ok', ['message' => '注册成功', 'redirect' => user_info_url('account')]);
172});
173
174// 更新个人信息 API
175mnbt_register_route('POST', '/account/api/update_profile', function ($params, $ctx) {
176 global $DB, $date;
177 $user = user_info_auth_current();
178 $email = trim($_POST['email'] ?? '');
179 $qq = trim($_POST['qq'] ?? '');
180
181 if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
182 user_info_json('邮箱格式不正确');
183 }
184 if ($email !== '' && strlen($email) > 128) {
185 user_info_json('邮箱过长');
186 }
187 if ($qq !== '' && !preg_match('/^[0-9]{5,12}$/', $qq)) {
188 user_info_json('QQ 号格式不正确');
189 }
190
191 $now = $date ?: date('Y-m-d H:i:s');
192 $ok = $DB->query_prepare(
193 "UPDATE MN_plugin_user SET email=?, qq=?, updated_at=? WHERE id=?",
194 [$email, $qq, $now, $user['id']]
195 );
196 if (!$ok) {
197 user_info_json('保存失败');
198 }
199 user_info_json('ok', ['message' => '保存成功']);
200}, 10, function () { return (bool)user_info_auth_current(); });
201
202// 修改密码 API
203mnbt_register_route('POST', '/account/api/change_password', function ($params, $ctx) {
204 global $DB, $date;
205 $user = user_info_auth_current();
206 $old_pass = $_POST['old_password'] ?? '';
207 $new_pass = $_POST['new_password'] ?? '';
208 $new_pass2 = $_POST['new_password2'] ?? '';
209
210 if (!password_verify($old_pass, $user['password_hash'])) {
211 user_info_json('原密码错误');
212 }
213 if (strlen($new_pass) < 6) {
214 user_info_json('新密码至少 6 个字符');
215 }
216 if ($new_pass !== $new_pass2) {
217 user_info_json('两次输入的新密码不一致');
218 }
219 if ($new_pass === $old_pass) {
220 user_info_json('新密码不能与原密码相同');
221 }
222
223 $hash = password_hash($new_pass, PASSWORD_BCRYPT);
224 $now = $date ?: date('Y-m-d H:i:s');
225 $ok = $DB->query_prepare(
226 "UPDATE MN_plugin_user SET password_hash=?, updated_at=? WHERE id=?",
227 [$hash, $now, $user['id']]
228 );
229 if (!$ok) {
230 user_info_json('修改失败');
231 }
232
233 user_info_auth_login($user['id'], $hash);
234 user_info_json('ok', ['message' => '修改成功']);
235}, 10, function () { return (bool)user_info_auth_current(); });
236
237/* ============================================================
238 * 管理员端页面注册
239 * ============================================================ */
240
241mnbt_register_page('admin', 'users', 'views/admin/users.php', '用户管理');
242mnbt_register_page('admin', 'user_edit', 'views/admin/user_edit.php', '用户编辑');
243
244mnbt_register_menu('admin', [
245 'title' => '用户管理',
246 'icon' => 'mdi-account-group',
247 'order' => 70,
248 'children' => [
249 ['title' => '用户列表', 'page' => 'users', 'icon' => 'mdi-format-list-bulleted', 'multitabs' => true],
250 ],
251]);
252
253// 管理员端 AJAX:重置用户密码
254mnbt_register_ajax('admin', 'user_info_admin_reset_password', function () {
255 global $DB, $date;
256 $user_id = (int)($_POST['user_id'] ?? 0);
257 $new_pass = trim((string)($_POST['new_password'] ?? ''));
258 if ($user_id <= 0) {
259 json_exit('参数错误');
260 }
261 if (strlen($new_pass) < 6) {
262 json_exit('新密码至少 6 个字符');
263 }
264 $row = $DB->get_row_prepare("SELECT id FROM MN_plugin_user WHERE id=? LIMIT 1", [$user_id]);
265 if (!$row) {
266 json_exit('用户不存在');
267 }
268 $hash = password_hash($new_pass, PASSWORD_BCRYPT);
269 $now = $date ?: date('Y-m-d H:i:s');
270 $ok = $DB->query_prepare(
271 "UPDATE MN_plugin_user SET password_hash=?, updated_at=? WHERE id=?",
272 [$hash, $now, $user_id]
273 );
274 if (!$ok) {
275 json_exit('重置失败');
276 }
277 json_exit('重置成功');
278}, 'admin');