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.
148 lines
4.7 KiB
148 lines
4.7 KiB
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\AdminUser;
|
|
use App\Models\OperationLog;
|
|
use App\Services\AdminMenuService;
|
|
use App\Services\GridMemberScopeService;
|
|
use App\Support\ApiResponse;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class AuthController extends Controller
|
|
{
|
|
use ApiResponse;
|
|
|
|
public function __construct(
|
|
protected AdminMenuService $menuService,
|
|
protected GridMemberScopeService $gridScope
|
|
) {}
|
|
|
|
public function login(Request $request): JsonResponse
|
|
{
|
|
$started = microtime(true);
|
|
$data = $request->validate([
|
|
'username' => ['required', 'string', 'max:64'],
|
|
'password' => ['required', 'string', 'max:255'],
|
|
]);
|
|
|
|
$admin = AdminUser::query()->where('username', $data['username'])->first();
|
|
if (! $admin || ! Hash::check($data['password'], $admin->password_hash)) {
|
|
throw ValidationException::withMessages([
|
|
'username' => ['账号或密码错误'],
|
|
]);
|
|
}
|
|
|
|
if ((int) $admin->status !== 1) {
|
|
$this->recordLoginOperationLog($admin, $request, $started, 403);
|
|
|
|
return $this->fail('账号已停用', 403);
|
|
}
|
|
|
|
$admin->forceFill([
|
|
'last_login_at' => now(),
|
|
'last_login_ip' => $request->ip(),
|
|
])->save();
|
|
|
|
$admin->tokens()->delete();
|
|
$token = $admin->createToken('admin-api')->plainTextToken;
|
|
|
|
$this->recordLoginOperationLog($admin, $request, $started, 200);
|
|
|
|
return $this->ok([
|
|
'token' => $token,
|
|
'token_type' => 'Bearer',
|
|
'user' => $this->userPayload($admin),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 登录时请求尚未通过 Sanctum 认证,操作日志中间件无法识别用户,故在控制器内单独写入。
|
|
*/
|
|
protected function recordLoginOperationLog(
|
|
AdminUser $admin,
|
|
Request $request,
|
|
float $startedAt,
|
|
int $responseCode,
|
|
): void {
|
|
OperationLog::query()->create([
|
|
'admin_user_id' => $admin->id,
|
|
'operator_name' => $admin->real_name ?: $admin->username,
|
|
'operated_at' => now(),
|
|
'http_method' => 'POST',
|
|
'api_path' => '/'.$request->path(),
|
|
'action_label' => $responseCode === 200 ? '管理员登录' : '管理员登录拒绝(账号停用)',
|
|
'ip' => $request->ip(),
|
|
'user_agent' => Str::limit((string) $request->userAgent(), 512, ''),
|
|
'request_summary' => ['username' => $admin->username],
|
|
'response_code' => $responseCode,
|
|
'duration_ms' => (int) round((microtime(true) - $startedAt) * 1000),
|
|
]);
|
|
}
|
|
|
|
public function logout(Request $request): JsonResponse
|
|
{
|
|
$request->user()?->currentAccessToken()?->delete();
|
|
|
|
return $this->ok(null, '已退出');
|
|
}
|
|
|
|
public function me(Request $request): JsonResponse
|
|
{
|
|
/** @var AdminUser $admin */
|
|
$admin = $request->user();
|
|
$admin->load('roles');
|
|
|
|
return $this->ok([
|
|
'user' => $this->userPayload($admin),
|
|
'permissions' => $admin->permissionCodes(),
|
|
'menus' => $this->menuService->treeForUser($admin),
|
|
]);
|
|
}
|
|
|
|
public function changePassword(Request $request): JsonResponse
|
|
{
|
|
$data = $request->validate([
|
|
'password' => ['required', 'string', 'min:6', 'max:255', 'confirmed'],
|
|
]);
|
|
|
|
/** @var AdminUser $admin */
|
|
$admin = $request->user();
|
|
|
|
$admin->forceFill([
|
|
'password_hash' => Hash::make($data['password']),
|
|
])->save();
|
|
|
|
return $this->ok(null, '密码已更新');
|
|
}
|
|
|
|
/** @return array<string, mixed> */
|
|
protected function userPayload(AdminUser $admin): array
|
|
{
|
|
return [
|
|
'id' => $admin->id,
|
|
'username' => $admin->username,
|
|
'real_name' => $admin->real_name,
|
|
'mobile' => $admin->mobile,
|
|
'email' => $admin->email,
|
|
'avatar_url' => $admin->avatar_url,
|
|
'status' => (int) $admin->status,
|
|
'roles' => $admin->roles->map(fn ($r) => [
|
|
'id' => $r->id,
|
|
'code' => $r->code,
|
|
'name' => $r->name,
|
|
])->values()->all(),
|
|
'is_super_admin' => $admin->isSuperAdmin(),
|
|
'is_grid_member' => $this->gridScope->isGridMember($admin),
|
|
'grid_scope' => $this->gridScope->isGridMember($admin)
|
|
? $this->gridScope->scopePayload($admin)
|
|
: null,
|
|
];
|
|
}
|
|
}
|