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 */ 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, ], ]; } }