From 13d63450c3ab8863f3d07438972f21210cfe9c1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=A4=80=ED=9D=A0?= Date: Thu, 6 Nov 2025 21:23:06 +0900 Subject: [PATCH] trafficmonitor init...2 --- app/Config/Constants.php | 2 +- app/Controllers/Auth/AuthController.php | 9 ++++++ app/DTOs/CertificationDTO.php | 14 ++++++--- app/Entities/UserEntity.php | 42 ++++++++++++++++++++----- app/Filters/AuthFilter.php | 2 +- app/Helpers/UserHelper.php | 28 ++++++++--------- app/Services/Auth/AuthService.php | 28 ++++++++++++++--- app/Views/admin/user/modify_form.php | 1 - 8 files changed, 91 insertions(+), 35 deletions(-) diff --git a/app/Config/Constants.php b/app/Config/Constants.php index 8837c71..4a5a932 100644 --- a/app/Config/Constants.php +++ b/app/Config/Constants.php @@ -395,5 +395,5 @@ define("ROLE", [ 'DIRECTOR' => "director", 'MASTER' => "master", ], - ['CLIENT'] => [] + 'CLIENT' => [], ]); diff --git a/app/Controllers/Auth/AuthController.php b/app/Controllers/Auth/AuthController.php index 7a66adc..4c9334a 100644 --- a/app/Controllers/Auth/AuthController.php +++ b/app/Controllers/Auth/AuthController.php @@ -76,4 +76,13 @@ abstract class AuthController extends CommonController return redirect()->back()->withInput()->with('error', "로그아웃 중 오류가 발생했습니다."); } } + protected function create_form_process(): void {} + protected function create_process(): RedirectResponse + { + return redirect()->to('/'); + } + protected function modify_form_process($uid): mixed + { + return new UserEntity(); + } } diff --git a/app/DTOs/CertificationDTO.php b/app/DTOs/CertificationDTO.php index e39e40c..adc9e76 100644 --- a/app/DTOs/CertificationDTO.php +++ b/app/DTOs/CertificationDTO.php @@ -3,13 +3,16 @@ namespace App\DTOs; use App\Services\Auth\AuthService; +use CodeIgniter\Entity\Entity; // DTO가 Entity를 상속받지 않는 경우, 필요한 경우 CommonDTO 또는 Entity 상속을 유지합니다. -class CertificationDTO extends CommonDTO +class CertificationDTO extends Entity // DTO가 Entity를 상속받는 것으로 가정합니다. { - public bool $isLogin = false; - public ?int $uid = null; + // 💡 role의 타입을 ?string에서 ?array로 변경합니다. + public ?string $uid = null; + public ?bool $isLogin = null; public ?string $name = null; - public ?string $role = null; + public ?array $role = null; + public function __construct(array $datas = []) { parent::__construct(); @@ -19,6 +22,7 @@ class CertificationDTO extends CommonDTO } } } + public static function fromByAuthService(AuthService $service): self { return new self( @@ -26,7 +30,7 @@ class CertificationDTO extends CommonDTO 'isLogin' => $service->isLoggedIn(), 'uid' => $service->getUID(), 'name' => $service->getName(), - 'role' => $service->getRole(), + 'role' => $service->getRole(), //배열(array|null)을 반환합니다. ] ); } diff --git a/app/Entities/UserEntity.php b/app/Entities/UserEntity.php index 57403ce..8a97ae9 100644 --- a/app/Entities/UserEntity.php +++ b/app/Entities/UserEntity.php @@ -4,6 +4,7 @@ namespace App\Entities; use App\Entities\CommonEntity; use App\Models\UserModel as Model; +use CodeIgniter\Entity\Entity; // Entity 클래스를 명시적으로 use 하는 것이 좋습니다. class UserEntity extends CommonEntity { @@ -11,9 +12,12 @@ class UserEntity extends CommonEntity const TITLE = Model::TITLE; const DEFAULT_STATUS = STATUS['AVAILABLE']; - // 💡 1. $casts 속성 추가: - // DB에 JSON 형태로 저장된 'role' 컬럼을 PHP에서 배열로 자동 변환합니다. + /** + * @var array Entity 속성을 DB에 저장하거나 DB에서 로드할 때의 형 변환 규칙 + */ protected $casts = [ + // 'role' 컬럼에 배열을 할당하면 DB에 JSON 문자열로 저장되며, + // DB에서 로드할 때 JSON 문자열이 자동으로 PHP 배열로 변환됩니다. 'role' => 'json-array', ]; @@ -26,21 +30,45 @@ class UserEntity extends CommonEntity { return $this->attributes['passwd']; } + // $formDatas['passwd']에 평문 비밀번호가 들어있으면, - //Model->insert시 Entity 생성자($formDatas)가 setPasswd()를 자동으로 호출합니다. + // Model->insert시 Entity 생성자($formDatas)가 setPasswd()를 자동으로 호출합니다. public function setPasswd(string $password) { + // 비밀번호를 암호화하여 저장합니다. $this->attributes['passwd'] = password_hash($password, PASSWORD_BCRYPT); } + /** * 사용자의 역할을 배열 형태로 반환합니다. - * $casts에 의해 DB에서 읽어올 때 이미 배열로 변환되어 있습니다. + * $casts에 의해 DB에서 읽어올 때 이미 배열로 변환될 것을 기대합니다. * @return array */ public function getRole(): array { - // 💡 2. 반환 타입을 array로 변경하고, - // null일 경우를 대비해 빈 배열을 반환하도록 처리합니다. - return $this->attributes['role'] ?? []; + $role = $this->attributes['role'] ?? []; + + // 1. $casts가 성공적으로 작동했거나, 이미 배열인 경우 바로 반환합니다. + if (is_array($role)) { + return $role; + } + + // 2. 캐스팅에 실패했으나 원본이 문자열로 남아있는 경우 (JSON 또는 CSV) + if (is_string($role) && !empty($role)) { + // 2-a. JSON 디코딩을 시도합니다. + $decodedRole = json_decode($role, true); + + if (json_last_error() === JSON_ERROR_NONE && is_array($decodedRole)) { + return $decodedRole; // 유효한 JSON 배열인 경우 + } + + // 2-b. JSON이 아니면 레거시 CSV 형식이라고 가정하고 explode로 변환합니다. + if (defined('DEFAULTS') && isset(DEFAULTS['DELIMITER_ROLE'])) { + return explode(DEFAULTS['DELIMITER_ROLE'], $role); + } + } + + // 3. 변환에 실패했거나 데이터가 없는 경우 빈 배열 반환 + return []; } } diff --git a/app/Filters/AuthFilter.php b/app/Filters/AuthFilter.php index 583db25..ef8fcb7 100644 --- a/app/Filters/AuthFilter.php +++ b/app/Filters/AuthFilter.php @@ -39,7 +39,7 @@ class AuthFilter implements FilterInterface if (!$auth->isAccessRole($arguments)) { return redirect()->back()->with( 'error', - "회원[{$auth->getNameByAuthInfo()}]님은 접속에 필요한 권한이 없습니다. " + "회원[{$auth->getName()}]님은 접속에 필요한 권한이 없습니다. " ); } } diff --git a/app/Helpers/UserHelper.php b/app/Helpers/UserHelper.php index b849a02..a0ea80a 100644 --- a/app/Helpers/UserHelper.php +++ b/app/Helpers/UserHelper.php @@ -2,6 +2,8 @@ namespace App\Helpers; +use App\Entities\UserEntity; + class UserHelper extends CommonHelper { public function __construct() @@ -16,23 +18,19 @@ class UserHelper extends CommonHelper $form = form_password($field, "", [...$extras]); break; case 'role': - // 💡 $value는 수정 폼 로드시 현재 Entity의 'role' 배열입니다. - // (old() 값이 있다면 old() 배열이 됩니다.) - $currentRoles = is_array($value) ? $value : []; - // 사용 가능한 모든 역할 목록 (Service 등에서 가져온다고 가정) - $allRoles = $viewDatas['control']['formOptions']['role'] ?? ROLE['USER']; + //$viewDatas['control']['entity']->$field에서 getRole()로 캐스팅이 되지 않아서 대체함 + if (($viewDatas['control']['entity'] ?? null) instanceof UserEntity) { + $value = $viewDatas['control']['entity']->getRole(); + } + $currentRoles = is_array($value) + ? array_map('strtolower', array_map('trim', $value)) + : []; $form = ''; - // 2. 각 역할에 대한 체크박스를 순회하며 생성 - foreach ($allRoles as $roleValue => $roleLabel) { - - // $roleLabel이 배열이 아닌 문자열만 있는 경우를 대비 - if (is_int($roleValue)) { - $roleValue = $roleLabel; - $roleLabel = ucfirst($roleValue); - } - $checked = in_array($roleValue, $currentRoles); - // 3. name="role[]" 형태로 배열 데이터 전송 준비 + //체크박스를 순회하며 생성 + foreach ($viewDatas['control']['formOptions']['role'] as $roleValue => $roleLabel) { + $checked = in_array(strtolower(trim($roleValue)), $currentRoles); $form .= ''; diff --git a/app/Services/Auth/AuthService.php b/app/Services/Auth/AuthService.php index 461b1e7..5a5f5b8 100644 --- a/app/Services/Auth/AuthService.php +++ b/app/Services/Auth/AuthService.php @@ -66,23 +66,41 @@ abstract class AuthService extends CommonService { return $this->getAuthInfo('name'); } - final public function getRole(): string|null + + /** + * 현재 로그인된 사용자의 역할을 배열 형태로 반환합니다. + * UserEntity::getRole()의 반환 타입과 일치시킵니다. + * @return array|null + */ + final public function getRole(): array|null // <-- 타입 힌트를 array|null로 변경 { + // getAuthInfo는 UserEntity에서 배열을 받아옵니다. return $this->getAuthInfo('role'); } + final public function isLoggedIn(): bool { return $this->getSession()->has(SESSION_NAMES['ISLOGIN']); } + + /** + * 사용자가 필요한 접근 권한($roles)을 가지고 있는지 확인합니다. + * @param array $roles 요구되는 권한 목록 + * @return bool + */ final public function isAccessRole(array $roles): bool { - $role = $this->getRole(); - if ($role === "") { + // (1) getRole()의 반환 타입이 이제 배열이므로 바로 받습니다. + $userRoles = $this->getRole(); + // 역할 정보 자체가 없거나 빈 배열인 경우 접근 불가 + if (empty($userRoles) || !is_array($userRoles)) { return false; } + // (2) 문자열 explode() 대신 array_intersect를 사용하여 배열 간의 공통점을 찾습니다. // 교집합이 없으면 false - return !empty(array_intersect(explode(DEFAULTS['DELIMITER_ROLE'], $role), $roles)); + return !empty(array_intersect($userRoles, $roles)); } + final public function pushCurrentUrl(string $url): void { $this->getSession()->set($this->url_stack_name, $url); @@ -103,7 +121,7 @@ abstract class AuthService extends CommonService 'uid' => $entity->getPK(), 'id' => $entity->getID(), 'name' => $entity->getTitle(), - 'role' => $entity->role + 'role' => $entity->getRole() ]); return $entity; } diff --git a/app/Views/admin/user/modify_form.php b/app/Views/admin/user/modify_form.php index e4af212..ef972fc 100644 --- a/app/Views/admin/user/modify_form.php +++ b/app/Views/admin/user/modify_form.php @@ -9,7 +9,6 @@ getFieldLabel($field, "", $viewDatas) ?> - getFieldForm($field, old($field) ?? ($viewDatas['control']['entity']->$field ?? null), $viewDatas) ?>