161 lines
5.2 KiB
PHP
161 lines
5.2 KiB
PHP
<?php
|
|
|
|
namespace app\controller\api;
|
|
|
|
use app\model\User;
|
|
use app\model\MembershipLevel;
|
|
use app\model\Role;
|
|
use app\service\JwtService;
|
|
use app\service\SettingsService;
|
|
use app\service\UserContextService;
|
|
|
|
class Auth extends BaseApi
|
|
{
|
|
public function guest()
|
|
{
|
|
$guestKey = strtolower(trim((string) $this->request->post('guest_key', '')));
|
|
if (!preg_match('/^[a-f0-9]{64}$/', $guestKey)) {
|
|
return $this->error('游客标识无效,请刷新页面重试', 422);
|
|
}
|
|
|
|
// Only persist a one-way fingerprint; the random browser key remains the credential.
|
|
$fingerprint = hash('sha256', $guestKey);
|
|
$username = 'guest_' . substr($fingerprint, 0, 32);
|
|
$user = User::where('username', $username)->find();
|
|
|
|
if (!$user) {
|
|
$roleId = Role::where('slug', 'user')->value('id');
|
|
$membershipId = MembershipLevel::where('slug', 'free')->value('id') ?: 1;
|
|
|
|
try {
|
|
$user = User::create([
|
|
'username' => $username,
|
|
'email' => $username . '@guest.local',
|
|
'password_hash' => password_hash(bin2hex(random_bytes(32)), PASSWORD_BCRYPT),
|
|
'nickname' => '访客',
|
|
'role' => 'user',
|
|
'role_id' => $roleId ?: null,
|
|
'membership_level_id' => $membershipId,
|
|
'status' => 'active',
|
|
]);
|
|
} catch (\Throwable $exception) {
|
|
// Two tabs may initialize the same browser guest at the same time.
|
|
$user = User::where('username', $username)->find();
|
|
if (!$user) {
|
|
throw $exception;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($user->status !== 'active') {
|
|
return $this->error('游客访问暂不可用', 403);
|
|
}
|
|
|
|
$token = JwtService::generateToken(['user_id' => $user->id]);
|
|
|
|
return $this->success([
|
|
'token' => $token,
|
|
'user' => $this->formatUser($user->id),
|
|
], '已进入游客模式');
|
|
}
|
|
|
|
public function register()
|
|
{
|
|
$allow = SettingsService::get('allow_register', true);
|
|
if ($allow !== true && $allow !== 'true') {
|
|
return $this->error('当前不允许注册');
|
|
}
|
|
|
|
$input = $this->request->post();
|
|
$username = trim($input['username'] ?? '');
|
|
$email = trim($input['email'] ?? '');
|
|
$password = $input['password'] ?? '';
|
|
|
|
if (strlen($username) < 3 || strlen($username) > 50) {
|
|
return $this->error('用户名长度需 3-50 个字符');
|
|
}
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
return $this->error('邮箱格式不正确');
|
|
}
|
|
if (strlen($password) < 6) {
|
|
return $this->error('密码至少 6 位');
|
|
}
|
|
|
|
if (User::where('username', $username)->whereOr('email', $email)->find()) {
|
|
return $this->error('用户名或邮箱已存在');
|
|
}
|
|
|
|
$defaultRoleId = \app\model\Role::where('slug', 'user')->value('id');
|
|
|
|
$user = User::create([
|
|
'username' => $username,
|
|
'email' => $email,
|
|
'password_hash' => password_hash($password, PASSWORD_BCRYPT),
|
|
'nickname' => $username,
|
|
'membership_level_id' => 1,
|
|
'role_id' => $defaultRoleId ?: null,
|
|
]);
|
|
|
|
$token = JwtService::generateToken(['user_id' => $user->id]);
|
|
|
|
return $this->success([
|
|
'token' => $token,
|
|
'user' => $this->formatUser($user->id),
|
|
], '注册成功');
|
|
}
|
|
|
|
public function login()
|
|
{
|
|
$input = $this->request->post();
|
|
$account = trim($input['account'] ?? '');
|
|
$password = $input['password'] ?? '';
|
|
|
|
if (!$account || !$password) {
|
|
return $this->error('请输入账号和密码');
|
|
}
|
|
|
|
$user = User::where(function ($query) use ($account) {
|
|
$query->where('username', $account)->whereOr('email', $account);
|
|
})->where('status', 'active')->find();
|
|
|
|
if (!$user || !password_verify($password, $user->password_hash)) {
|
|
return $this->error('账号或密码错误', 401);
|
|
}
|
|
|
|
$user->save(['last_login_at' => date('Y-m-d H:i:s')]);
|
|
$token = JwtService::generateToken(['user_id' => $user->id]);
|
|
|
|
return $this->success([
|
|
'token' => $token,
|
|
'user' => $this->formatUser($user->id),
|
|
], '登录成功');
|
|
}
|
|
|
|
public function me()
|
|
{
|
|
return $this->success($this->authUser());
|
|
}
|
|
|
|
public function updateProfile()
|
|
{
|
|
$user = $this->authUser();
|
|
$nickname = trim($this->request->put('nickname', ''));
|
|
|
|
if ($nickname) {
|
|
User::where('id', $user['id'])->update(['nickname' => $nickname]);
|
|
}
|
|
|
|
return $this->success($this->formatUser($user['id']));
|
|
}
|
|
|
|
public function logout()
|
|
{
|
|
return $this->success(null, '已退出');
|
|
}
|
|
|
|
private function formatUser(int $userId): array
|
|
{
|
|
return UserContextService::formatPublicUser($userId);
|
|
}
|
|
}
|