You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
5.6 KiB
179 lines
5.6 KiB
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\AdminUser;
|
|
use App\Models\Competition;
|
|
use App\Models\CompetitionAdmin;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class ManageAuthController extends Controller
|
|
{
|
|
public function login(Request $request): JsonResponse
|
|
{
|
|
$data = $request->validate([
|
|
'username' => ['required', 'string', 'max:64'],
|
|
'password' => ['required', 'string', 'max:255'],
|
|
'competition_slug' => ['required', 'string', 'max:64'],
|
|
]);
|
|
|
|
$competition = Competition::query()
|
|
->where('slug', $data['competition_slug'])
|
|
->first();
|
|
|
|
if ($competition === null) {
|
|
throw ValidationException::withMessages([
|
|
'competition_slug' => ['赛事不存在'],
|
|
]);
|
|
}
|
|
|
|
$platform = AdminUser::query()->where('username', $data['username'])->first();
|
|
if ($platform !== null) {
|
|
$this->assertActivePassword($platform, $data['password']);
|
|
$platform->forceFill(['last_login_at' => now()])->save();
|
|
$token = $platform->createToken('admin')->plainTextToken;
|
|
|
|
return response()->json($this->payload(
|
|
$token,
|
|
'platform',
|
|
[
|
|
'id' => $platform->id,
|
|
'username' => $platform->username,
|
|
'name' => $platform->name,
|
|
],
|
|
$competition,
|
|
));
|
|
}
|
|
|
|
$admin = CompetitionAdmin::query()
|
|
->where('competition_id', $competition->id)
|
|
->where('username', $data['username'])
|
|
->first();
|
|
|
|
if ($admin === null || $admin->status !== 'active') {
|
|
throw ValidationException::withMessages([
|
|
'username' => ['账号不存在或不可用'],
|
|
]);
|
|
}
|
|
|
|
$this->assertActivePassword($admin, $data['password']);
|
|
$admin->forceFill(['last_login_at' => now()])->save();
|
|
$admin->tokens()->where('name', 'manage')->delete();
|
|
$token = $admin->createToken('manage')->plainTextToken;
|
|
|
|
return response()->json($this->payload(
|
|
$token,
|
|
'competition',
|
|
[
|
|
'id' => $admin->id,
|
|
'username' => $admin->username,
|
|
'name' => $admin->name,
|
|
],
|
|
$competition,
|
|
));
|
|
}
|
|
|
|
public function me(Request $request): JsonResponse
|
|
{
|
|
$user = $request->user();
|
|
if ($user instanceof AdminUser) {
|
|
return response()->json([
|
|
'kind' => 'platform',
|
|
'user' => [
|
|
'id' => $user->id,
|
|
'username' => $user->username,
|
|
'name' => $user->name,
|
|
],
|
|
]);
|
|
}
|
|
|
|
/** @var CompetitionAdmin $user */
|
|
$user->load('competition:id,slug,name');
|
|
|
|
return response()->json([
|
|
'kind' => 'competition',
|
|
'user' => [
|
|
'id' => $user->id,
|
|
'username' => $user->username,
|
|
'name' => $user->name,
|
|
],
|
|
'competition' => [
|
|
'id' => $user->competition?->id,
|
|
'slug' => $user->competition?->slug,
|
|
'name' => $user->competition?->name,
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function changePassword(Request $request): JsonResponse
|
|
{
|
|
$data = $request->validate([
|
|
'current_password' => ['required', 'string', 'max:255'],
|
|
'password' => ['required', 'string', 'min:6', 'max:255', 'confirmed'],
|
|
]);
|
|
|
|
$user = $request->user();
|
|
if (! $user instanceof AdminUser && ! $user instanceof CompetitionAdmin) {
|
|
abort(403);
|
|
}
|
|
|
|
$hash = $user->getAuthPassword();
|
|
if ($hash === null || $hash === '' || ! Hash::check($data['current_password'], $hash)) {
|
|
throw ValidationException::withMessages([
|
|
'current_password' => ['当前密码不正确'],
|
|
]);
|
|
}
|
|
|
|
$user->forceFill(['password_hash' => $data['password']])->save();
|
|
|
|
return response()->json(['message' => '密码已更新']);
|
|
}
|
|
|
|
private function assertActivePassword(AdminUser|CompetitionAdmin $user, string $password): void
|
|
{
|
|
if ($user instanceof AdminUser && $user->status !== 'active') {
|
|
throw ValidationException::withMessages([
|
|
'username' => ['账号不存在或不可用'],
|
|
]);
|
|
}
|
|
|
|
$hash = $user->getAuthPassword();
|
|
if ($hash === null || $hash === '') {
|
|
throw ValidationException::withMessages([
|
|
'username' => ['该账号未配置密码'],
|
|
]);
|
|
}
|
|
|
|
if (! Hash::check($password, $hash)) {
|
|
throw ValidationException::withMessages([
|
|
'username' => ['账号或密码错误'],
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array{id: int, username: ?string, name: ?string} $user
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function payload(string $token, string $kind, array $user, Competition $competition): array
|
|
{
|
|
return [
|
|
'token_type' => 'Bearer',
|
|
'access_token' => $token,
|
|
'token' => $token,
|
|
'kind' => $kind,
|
|
'user' => $user,
|
|
'admin' => $user,
|
|
'competition' => [
|
|
'id' => $competition->id,
|
|
'slug' => $competition->slug,
|
|
'name' => $competition->name,
|
|
],
|
|
];
|
|
}
|
|
}
|