| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- <?php
- namespace App\Controllers\Api;
- use CodeIgniter\HTTP\ResponseInterface;
- class AuthController extends BaseApiController
- {
- /**
- * Login
- */
- public function login()
- {
- $json = $this->request->getJSON();
- $username = $json->username ?? '';
- $password = $json->password ?? '';
- if (empty($username) || empty($password)) {
- return $this->respondError('아이디와 비밀번호를 입력하세요.');
- }
- // Find admin user (삭제된 계정 제외)
- $builder = $this->getDB()->table('admin_users');
- $admin = $builder
- ->where('username', $username)
- ->where('deleted_YN', 'N')
- ->get()->getRow();
- if (!$admin) {
- return $this->respondError('아이디 또는 비밀번호가 올바르지 않습니다.');
- }
- // Check if account is locked (5 failed attempts)
- $loginAttempts = $admin->login_attempts ?? 0;
- if ($loginAttempts >= 5) {
- return $this->respondError('계정이 잠겼습니다. 슈퍼 관리자에게 문의하여주세요.', ResponseInterface::HTTP_FORBIDDEN);
- }
- // Check if admin is active
- if ($admin->status !== 'active') {
- return $this->respondError('비활성화된 계정입니다. 관리자에게 문의하세요.');
- }
- // Verify password
- if (!password_verify($password, $admin->password)) {
- // Increment login attempts
- $newAttempts = $loginAttempts + 1;
- $updateBuilder = $this->getDB()->table('admin_users');
- $updateBuilder->where('id', $admin->id)->update([
- 'login_attempts' => $newAttempts,
- 'last_failed_login' => date('Y-m-d H:i:s')
- ]);
- // Check if account should be locked
- if ($newAttempts >= 5) {
- return $this->respondError('비밀번호를 5회 틀렸습니다. 계정이 잠겼습니다. 슈퍼 관리자에게 문의하여주세요.', ResponseInterface::HTTP_FORBIDDEN);
- }
- $remainingAttempts = 5 - $newAttempts;
- return $this->respondError("아이디 또는 비밀번호가 올바르지 않습니다. (남은 시도 횟수: {$remainingAttempts}회)");
- }
- // Reset login attempts + last_login 업데이트
- $resetBuilder = $this->getDB()->table('admin_users');
- $resetBuilder->where('id', $admin->id)->update([
- 'login_attempts' => 0,
- 'last_failed_login' => null,
- 'last_login' => date('Y-m-d H:i:s'),
- ]);
- // Generate token
- $token = bin2hex(random_bytes(32));
- $expiresAt = date('Y-m-d H:i:s', strtotime('+24 hours'));
- // Save token
- $tokenBuilder = $this->getDB()->table('admin_tokens');
- $tokenBuilder->insert([
- 'admin_id' => $admin->id,
- 'token' => $token,
- 'expires_at' => $expiresAt,
- 'created_at' => date('Y-m-d H:i:s')
- ]);
- // Check if password change is needed (6 months)
- $passwordChangeNeeded = false;
- if (!empty($admin->password_changed_at)) {
- $sixMonthsAgo = strtotime('-6 months');
- $passwordChangedTime = strtotime($admin->password_changed_at);
- $passwordChangeNeeded = $passwordChangedTime < $sixMonthsAgo;
- } else {
- // password_changed_at이 없으면 created_at 기준으로 체크
- if (!empty($admin->created_at)) {
- $sixMonthsAgo = strtotime('-6 months');
- $createdTime = strtotime($admin->created_at);
- $passwordChangeNeeded = $createdTime < $sixMonthsAgo;
- }
- }
- return $this->respondSuccess([
- 'token' => $token,
- 'expires_at' => $expiresAt,
- 'password_change_needed' => $passwordChangeNeeded,
- 'admin' => [
- 'id' => $admin->id,
- 'username' => $admin->username,
- 'name' => $admin->name,
- 'email' => $admin->email,
- 'role' => $admin->role,
- 'permissions' => $this->fetchPermissions((int) $admin->id, $admin->role),
- ]
- ], '로그인 성공');
- }
- /**
- * 관리자 권한 배열 반환 — super_admin은 'all', admin은 메뉴 id 배열
- */
- private function fetchPermissions(int $adminId, string $role)
- {
- if ($role === 'super_admin') return 'all';
- $rows = $this->getDB()->table('admin_permissions')
- ->select('permission')
- ->where('admin_id', $adminId)
- ->get()->getResult();
- return array_map(fn($r) => $r->permission, $rows);
- }
- /**
- * Logout
- */
- public function logout()
- {
- $tokenData = parent::validateToken();
- if ($tokenData) {
- $builder = $this->getDB()->table('admin_tokens');
- $builder->where('token', $tokenData->token)->delete();
- }
- return $this->respondSuccess(null, '로그아웃 성공');
- }
- /**
- * Check token (API endpoint)
- */
- public function check()
- {
- $tokenData = $this->requireAuth();
- if ($tokenData instanceof ResponseInterface) {
- return $tokenData;
- }
- // Get admin info
- $builder = $this->getDB()->table('admin_users');
- $admin = $builder->where('id', $tokenData->admin_id)->get()->getRow();
- return $this->respondSuccess([
- 'admin' => [
- 'id' => $admin->id,
- 'username' => $admin->username,
- 'name' => $admin->name,
- 'email' => $admin->email,
- 'role' => $admin->role,
- 'permissions' => $this->fetchPermissions((int) $admin->id, $admin->role),
- ]
- ]);
- }
- }
|