trafficmonitor init...2
This commit is contained in:
parent
c6219c0aab
commit
7621ea514b
@ -2,18 +2,15 @@
|
||||
|
||||
namespace App\Controllers\Auth;
|
||||
|
||||
use App\DTOs\Auth\GoogleDTO;
|
||||
use App\Entities\UserEntity;
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use App\Libraries\MySocket\GoogleSocket\API as GoogleSocket;
|
||||
use App\Entities\UserEntity;
|
||||
|
||||
class GoogleController extends AuthController
|
||||
{
|
||||
public const PATH = 'login';
|
||||
private ?GoogleSocket $_socket = null;
|
||||
private $_service = null;
|
||||
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
|
||||
{
|
||||
parent::initController($request, $response, $logger);
|
||||
@ -27,15 +24,12 @@ class GoogleController extends AuthController
|
||||
//구글 로그인 BUTTON용
|
||||
$this->addViewDatas('SNSButton', anchor($this->service->socket->createAuthUrl(), ICONS['GOOGLE'] . 'Google 로그인', ["class" => "btn-google"]));
|
||||
}
|
||||
|
||||
//로그인처리
|
||||
protected function login_process(): UserEntity
|
||||
{
|
||||
$formDatas = $this->doValidation($this->getViewDatas('action'));
|
||||
if (!array_key_exists('access_code', $formDatas) || !$formDatas['access_code']) {
|
||||
throw new \Exception("구글 로그인 실패");
|
||||
}
|
||||
return $this->service->login($formDatas);
|
||||
//요청 데이터를 DTO 객체로 변환
|
||||
$dto = new GoogleDTO($this->request->getPost());
|
||||
return $this->service->login($dto);
|
||||
}
|
||||
protected function logout_process(): void
|
||||
{
|
||||
|
||||
@ -27,7 +27,6 @@ class LocalController extends AuthController
|
||||
//로그인처리
|
||||
protected function login_process(): UserEntity
|
||||
{
|
||||
//요청 데이터를 DTO 객체로 변환
|
||||
$dto = new LocalDTO($this->request->getPost());
|
||||
return $this->service->login($dto);
|
||||
}
|
||||
|
||||
@ -23,14 +23,11 @@ abstract class CommonController extends BaseController
|
||||
private array $_action_paths = [];
|
||||
private array $_viewDatas = [];
|
||||
protected $service = null;
|
||||
protected $authService = null;
|
||||
protected $myCertification = null;
|
||||
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
|
||||
{
|
||||
parent::initController($request, $response, $logger);
|
||||
//로그인관련
|
||||
$this->authService = service('myauth');
|
||||
$this->myCertification = CertificationDTO::fromByAuthService($this->authService);
|
||||
$this->myCertification = CertificationDTO::byAuthContext(service('myauth')->getAuthContext());
|
||||
}
|
||||
protected function getLayout(): string
|
||||
{
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\DTOs;
|
||||
|
||||
use App\Services\Auth\AuthService;
|
||||
use App\Libraries\AuthContext;
|
||||
use CodeIgniter\Entity\Entity; // DTO가 Entity를 상속받지 않는 경우, 필요한 경우 CommonDTO 또는 Entity 상속을 유지합니다.
|
||||
|
||||
class CertificationDTO extends Entity // DTO가 Entity를 상속받는 것으로 가정합니다.
|
||||
@ -22,15 +22,15 @@ class CertificationDTO extends Entity // DTO가 Entity를 상속받는 것으로
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function fromByAuthService(AuthService $service): self
|
||||
//인증 정보
|
||||
public static function byAuthContext(AuthContext $authContext): self
|
||||
{
|
||||
return new self(
|
||||
[
|
||||
'isLogin' => $service->isLoggedIn(),
|
||||
'uid' => $service->getUID(),
|
||||
'name' => $service->getName(),
|
||||
'role' => $service->getRole(), //배열(array|null)을 반환합니다.
|
||||
'isLogin' => $authContext->isLoggedIn(),
|
||||
'uid' => $authContext->getUID(),
|
||||
'name' => $authContext->getName(),
|
||||
'role' => $authContext->getRole(), //배열(array|null)을 반환합니다.
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@ -26,20 +26,20 @@ class AuthFilter implements FilterInterface
|
||||
*/
|
||||
public function before(RequestInterface $request, $arguments = null)
|
||||
{
|
||||
$auth = service('myauth');
|
||||
$authContext = service('myauth')->getAuthContext();
|
||||
// var_dump($arguments);
|
||||
// log_message("debug", var_export($arguments, true));
|
||||
// exit;
|
||||
// 로그인 않했으면
|
||||
if (!$auth->isLoggedIn()) {
|
||||
$auth->pushCurrentUrl($request->getUri()->getPath() . ($request->getUri()->getQuery() ? "?" . $request->getUri()->getQuery() : ""));
|
||||
if (!$authContext->isLoggedIn()) {
|
||||
$authContext->pushCurrentUrl($request->getUri()->getPath() . ($request->getUri()->getQuery() ? "?" . $request->getUri()->getQuery() : ""));
|
||||
return redirect()->to(URLS['LOGIN'])->with('error', '로그인을하셔야합니다.');
|
||||
}
|
||||
//User Role 비교 // 회원 ROLES이 필요ROLE($arguments) 목록에 존재하지 않으면(ACL)
|
||||
if (!$auth->isAccessRole($arguments)) {
|
||||
if (!$authContext->isAccessRole($arguments)) {
|
||||
return redirect()->back()->with(
|
||||
'error',
|
||||
"회원[{$auth->getName()}]님은 접속에 필요한 권한이 없습니다. "
|
||||
"회원[{$authContext->getName()}]님은 접속에 필요한 권한이 없습니다. "
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ class TrafficHelper extends CommonHelper
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->setTitleField(TrafficModel::TITLE);
|
||||
}
|
||||
public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string
|
||||
{
|
||||
|
||||
137
app/Libraries/AuthContext.php
Normal file
137
app/Libraries/AuthContext.php
Normal file
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace App\Libraries;
|
||||
|
||||
use App\Entities\UserEntity;
|
||||
use CodeIgniter\Session\Session;
|
||||
|
||||
/**
|
||||
* AuthContext
|
||||
* 인증 세션의 저장, 조회 및 파괴를 관리합니다.
|
||||
* AuthService의 세션 로직을 분리하여 SRP를 준수합니다.
|
||||
*/
|
||||
class AuthContext
|
||||
{
|
||||
private Session $session;
|
||||
private string $urlStackName = "url_stack";
|
||||
|
||||
// 환경 설정에서 정의된 상수라고 가정합니다.
|
||||
const SESSION_IS_LOGIN = 'ISLOGIN';
|
||||
const SESSION_AUTH_INFO = 'AUTH';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// 세션 서비스를 직접 사용합니다.
|
||||
$this->session = \Config\Services::session();
|
||||
}
|
||||
|
||||
private function getAuthInfo(string $key = ""): array|string|null
|
||||
{
|
||||
$authInfo = $this->session->get(self::SESSION_AUTH_INFO);
|
||||
if ($key) {
|
||||
return $authInfo[$key] ?? null;
|
||||
}
|
||||
return $authInfo;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
// Public Accessors (AuthService에서 이동)
|
||||
// ----------------------------------------------------
|
||||
|
||||
public function getUID(): string|null
|
||||
{
|
||||
return $this->getAuthInfo('uid');
|
||||
}
|
||||
|
||||
public function getID(): string|null
|
||||
{
|
||||
return $this->getAuthInfo('id');
|
||||
}
|
||||
|
||||
public function getName(): string|null
|
||||
{
|
||||
return $this->getAuthInfo('name');
|
||||
}
|
||||
|
||||
public function getRole(): array|null
|
||||
{
|
||||
return $this->getAuthInfo('role');
|
||||
}
|
||||
|
||||
public function isLoggedIn(): bool
|
||||
{
|
||||
return $this->session->has(self::SESSION_IS_LOGIN);
|
||||
}
|
||||
|
||||
public function isAccessRole(array $roles): bool
|
||||
{
|
||||
$userRoles = $this->getRole();
|
||||
if (empty($userRoles) || !is_array($userRoles)) {
|
||||
return false;
|
||||
}
|
||||
return !empty(array_intersect($userRoles, $roles));
|
||||
}
|
||||
|
||||
public function pushCurrentUrl(string $url): void
|
||||
{
|
||||
$this->session->set($this->urlStackName, $url);
|
||||
}
|
||||
|
||||
public function popPreviousUrl(): string
|
||||
{
|
||||
$url = $this->session->get($this->urlStackName) ?? "";
|
||||
if (!empty($url)) {
|
||||
$this->session->set($this->urlStackName, ""); // 세션에서 제거
|
||||
return $url;
|
||||
}
|
||||
return '/';
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
// Session Writers (Login/Logout Process)
|
||||
// ----------------------------------------------------
|
||||
|
||||
/**
|
||||
* 인증 성공 후 세션에 사용자 정보를 기록합니다.
|
||||
*/
|
||||
public function setAuthSession(UserEntity $entity): void
|
||||
{
|
||||
$this->session->set(self::SESSION_IS_LOGIN, true);
|
||||
$this->session->set(self::SESSION_AUTH_INFO, [
|
||||
'uid' => $entity->getPK(),
|
||||
'id' => $entity->getID(),
|
||||
'name' => $entity->getTitle(),
|
||||
'role' => $entity->getRole()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그아웃 시 세션 및 쿠키를 파괴합니다.
|
||||
*/
|
||||
public function destroyAuthSession(): void
|
||||
{
|
||||
// 세션 데이터 삭제
|
||||
$this->session->remove(self::SESSION_IS_LOGIN);
|
||||
$this->session->remove(self::SESSION_AUTH_INFO);
|
||||
|
||||
// 모든 세션 데이터 삭제
|
||||
$this->session->destroy();
|
||||
|
||||
// 세션 쿠키 삭제 (AuthService에서 가져온 로직)
|
||||
if (ini_get("session.use_cookies")) {
|
||||
$params = session_get_cookie_params();
|
||||
setcookie(
|
||||
session_name(),
|
||||
'',
|
||||
time() - 42000,
|
||||
$params["path"],
|
||||
$params["domain"],
|
||||
$params["secure"],
|
||||
$params["httponly"]
|
||||
);
|
||||
}
|
||||
// 세션 재생성
|
||||
session_start();
|
||||
$this->session->regenerate(true);
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@ class TrafficModel extends CommonModel
|
||||
{
|
||||
const TABLE = "trafficinfo";
|
||||
const PK = "uid";
|
||||
const TITLE = "title";
|
||||
const TITLE = "switch";
|
||||
protected $table = self::TABLE;
|
||||
// protected $useAutoIncrement = false;
|
||||
protected $primaryKey = self::PK;
|
||||
@ -17,21 +17,10 @@ class TrafficModel extends CommonModel
|
||||
protected $allowedFields = [
|
||||
"uid",
|
||||
"user_uid",
|
||||
"clientinfo_uid",
|
||||
"serverinfo_uid",
|
||||
"payment_uid",
|
||||
"code",
|
||||
"title",
|
||||
"site",
|
||||
"location",
|
||||
"rack",
|
||||
"line",
|
||||
"billing_at",
|
||||
"sale",
|
||||
"amount",
|
||||
"start_at",
|
||||
"end_at",
|
||||
"history",
|
||||
"switch",
|
||||
"index",
|
||||
"in",
|
||||
"out",
|
||||
"status",
|
||||
"updated_at"
|
||||
];
|
||||
@ -39,11 +28,4 @@ class TrafficModel extends CommonModel
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
public function getFormRule(string $action, string $field): string
|
||||
//입력전 코드처리
|
||||
final public function create(array $formDatas): ServiceEntity
|
||||
{
|
||||
$formDatas['code'] = $formDatas['site'] . "_s" . uniqid();
|
||||
return parent::create($formDatas);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,148 +5,117 @@ namespace App\Services\Auth;
|
||||
use App\Entities\UserEntity;
|
||||
use App\Helpers\AuthHelper;
|
||||
use App\Models\CommonModel;
|
||||
use App\Services\CommonService;
|
||||
use CodeIgniter\Session\Session;
|
||||
use App\Libraries\AuthContext;
|
||||
use CodeIgniter\Validation\Exceptions\ValidationException;
|
||||
|
||||
|
||||
// 참고:https://github.com/SyntaxPhoenix/iloclient
|
||||
abstract class AuthService extends CommonService
|
||||
/**
|
||||
* AuthService
|
||||
* 인증(로그인) 워크플로우를 정의하는 템플릿 클래스입니다.
|
||||
* CommonService를 상속받지 않아 불필요한 CRUD 구현을 요구하지 않습니다.
|
||||
*/
|
||||
abstract class AuthService
|
||||
{
|
||||
private ?Session $_session = null;
|
||||
private $url_stack_name = "url_stack";
|
||||
private ?AuthContext $_authContext = null;
|
||||
private array $_classPaths = [];
|
||||
protected $formServiceInstance = null;
|
||||
protected ?CommonModel $model = null;
|
||||
protected ?AuthHelper $helperInstance = null;
|
||||
|
||||
protected function __construct(CommonModel $model)
|
||||
{
|
||||
parent::__construct($model);
|
||||
$this->model = $model; // 모델을 직접 주입받아 자식에게 전달
|
||||
$this->addClassPaths('Auth');
|
||||
}
|
||||
abstract public function login(mixed $dto): UserEntity;
|
||||
abstract public function getFormService(): mixed;
|
||||
final public function getHelper(): AuthHelper
|
||||
{
|
||||
if ($this->helperInstance === null) {
|
||||
$this->helperInstance = new AuthHelper();
|
||||
// AuthHelper에 필요한 기본 메타데이터만 설정합니다. (CRUD 제거)
|
||||
$this->helperInstance->setAttributes([
|
||||
'pk_field' => $this->model->getPKField(),
|
||||
'title_field' => $this->model->getTitleField(),
|
||||
'table' => $this->model->getTable(),
|
||||
'useAutoIncrement' => $this->model->useAutoIncrement(),
|
||||
'class_path' => $this->getClassPaths(false)
|
||||
'class_path' => $this->getClassPaths(false)
|
||||
]);
|
||||
}
|
||||
return $this->helperInstance;
|
||||
}
|
||||
//Index,FieldForm관련
|
||||
final public function getSession(): Session
|
||||
//인증세션용
|
||||
final public function getAuthContext(): AuthContext
|
||||
{
|
||||
if ($this->_session === null) {
|
||||
$this->_session = \Config\Services::session();
|
||||
if ($this->_authContext === null) {
|
||||
$this->_authContext = new AuthContext();
|
||||
}
|
||||
return $this->_session;
|
||||
return $this->_authContext;
|
||||
}
|
||||
private function getAuthInfo(string $key = ""): array|string|null
|
||||
final protected function addClassPaths(string $path): void
|
||||
{
|
||||
$authInfo = $this->getSession()->get(SESSION_NAMES['AUTH']);
|
||||
if ($key) {
|
||||
return $authInfo[$key] ?? null;
|
||||
}
|
||||
return $authInfo;
|
||||
$this->_classPaths[] = $path;
|
||||
}
|
||||
public function getFormFields(): array
|
||||
final public function getClassPaths($isArray = true, $delimeter = DIRECTORY_SEPARATOR): array|string
|
||||
{
|
||||
return ['id', 'passwd'];
|
||||
return $isArray ? $this->_classPaths : implode($delimeter, $this->_classPaths);
|
||||
}
|
||||
final public function getUID(): string|null
|
||||
protected function getEntity_process(mixed $entity): mixed
|
||||
{
|
||||
return $this->getAuthInfo('uid');
|
||||
}
|
||||
final public function getID(): string|null
|
||||
{
|
||||
return $this->getAuthInfo('id');
|
||||
}
|
||||
final public function getName(): string|null
|
||||
{
|
||||
return $this->getAuthInfo('name');
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 로그인된 사용자의 역할을 배열 형태로 반환합니다.
|
||||
* 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
|
||||
{
|
||||
// (1) getRole()의 반환 타입이 이제 배열이므로 바로 받습니다.
|
||||
$userRoles = $this->getRole();
|
||||
// 역할 정보 자체가 없거나 빈 배열인 경우 접근 불가
|
||||
if (empty($userRoles) || !is_array($userRoles)) {
|
||||
return false;
|
||||
}
|
||||
// (2) 문자열 explode() 대신 array_intersect를 사용하여 배열 간의 공통점을 찾습니다.
|
||||
// 교집합이 없으면 false
|
||||
return !empty(array_intersect($userRoles, $roles));
|
||||
}
|
||||
|
||||
final public function pushCurrentUrl(string $url): void
|
||||
{
|
||||
$this->getSession()->set($this->url_stack_name, $url);
|
||||
}
|
||||
final public function popPreviousUrl(): string
|
||||
{
|
||||
$url = $this->getSession()->get($this->url_stack_name) ?? "";
|
||||
if (!empty($url)) {
|
||||
$this->pushCurrentUrl("");
|
||||
return $url;
|
||||
}
|
||||
return '/'; // 기본 URL
|
||||
}
|
||||
final protected function login_process(UserEntity $entity): UserEntity
|
||||
{
|
||||
$this->getSession()->set(SESSION_NAMES['ISLOGIN'], true);
|
||||
$this->getSession()->set(SESSION_NAMES['AUTH'], [
|
||||
'uid' => $entity->getPK(),
|
||||
'id' => $entity->getID(),
|
||||
'name' => $entity->getTitle(),
|
||||
'role' => $entity->getRole()
|
||||
]);
|
||||
return $entity;
|
||||
}
|
||||
final public function getEntity(string|int|array $where, ?string $message = null): mixed
|
||||
{
|
||||
try {
|
||||
$entity = is_array($where) ? $this->model->where($where)->first() : $this->model->find($where);
|
||||
if (!$entity) {
|
||||
return null;
|
||||
}
|
||||
if (is_array($entity)) {
|
||||
throw new \Exception(__METHOD__ . "에서 결과값 Array 오류발생:\n" . var_export($entity, true));
|
||||
}
|
||||
return $this->getEntity_process($entity);
|
||||
} catch (\Exception $e) {
|
||||
$message = sprintf(
|
||||
"\n------%s SQL오류-----<BR>\n%s\n%s\n------------------------------\n",
|
||||
__FUNCTION__,
|
||||
$this->model->getLastQuery(),
|
||||
$e->getMessage()
|
||||
);
|
||||
throw new \Exception($message);
|
||||
}
|
||||
}
|
||||
final protected function getValidationRules(string $action, array $allRules = []): array
|
||||
{
|
||||
foreach ($this->getFormService()->getFormFields($action) as $field) {
|
||||
$allRules = array_merge($allRules, $this->getValidationRule($action, $field, $allRules));
|
||||
}
|
||||
return $allRules;
|
||||
}
|
||||
protected function getValidationRule(string $action, string $field, array $rules = []): array
|
||||
{
|
||||
switch ($field) {
|
||||
default:
|
||||
$rules[$field] = $this->getFormService()->getValidationRule($action, $field);
|
||||
break;
|
||||
}
|
||||
return $rules;
|
||||
}
|
||||
|
||||
//로그인
|
||||
abstract protected function login_process(array $formDatas): UserEntity;
|
||||
public function login(object $dto): UserEntity
|
||||
{
|
||||
//입력값 검증
|
||||
$formDatas = (array) $dto;
|
||||
if (!service('validation')->setRules($this->getValidationRules(__FUNCTION__))->run($formDatas)) {
|
||||
throw new ValidationException(implode("\n", service('validation')->getErrors()));
|
||||
}
|
||||
//인증처리
|
||||
$entity = $this->login_process($formDatas);
|
||||
//세션처리
|
||||
$this->getAuthContext()->setAuthSession($entity);
|
||||
return $entity;
|
||||
}
|
||||
//로그아웃
|
||||
final public function logout(): void
|
||||
{
|
||||
// 세션 데이터 삭제
|
||||
$this->getSession()->remove(SESSION_NAMES['ISLOGIN']);
|
||||
$this->getSession()->remove(SESSION_NAMES['AUTH']);
|
||||
// 모든 세션 데이터 삭제
|
||||
$this->getSession()->destroy();
|
||||
// 세션 쿠키 삭제
|
||||
if (ini_get("session.use_cookies")) {
|
||||
$params = session_get_cookie_params();
|
||||
setcookie(
|
||||
session_name(),
|
||||
'',
|
||||
time() - 42000,
|
||||
$params["path"],
|
||||
$params["domain"],
|
||||
$params["secure"],
|
||||
$params["httponly"]
|
||||
);
|
||||
}
|
||||
// 세션 재생성
|
||||
session_start();
|
||||
$this->getSession()->regenerate(true);
|
||||
$this->getAuthContext()->destroyAuthSession();
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,39 +33,18 @@ class GoogleService extends AuthService
|
||||
}
|
||||
return $this->formServiceInstance;
|
||||
}
|
||||
public function getFormFields(): array
|
||||
{
|
||||
return ["access_code"];
|
||||
}
|
||||
public function getFormFilters(): array
|
||||
{
|
||||
return ["access_code"];
|
||||
}
|
||||
public function getBatchjobButtons(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
//기본기능
|
||||
public function login(mixed $dto): UserEntity
|
||||
protected function login_process(array $formDatas): UserEntity
|
||||
{
|
||||
try {
|
||||
if (!$dto instanceof GoogleDTO) {
|
||||
throw new RuntimeException(__METHOD__ . "에서 오류발생: GoogleDTO만 사용하실수 있습니다");
|
||||
}
|
||||
// DTO 객체를 배열로 변환하여 검증기에 전달
|
||||
$formDatas = (array) $dto;
|
||||
if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) {
|
||||
// 검증 실패 시, ValidationException을 던집니다.
|
||||
throw new ValidationException(service('validation')->getErrors());
|
||||
}
|
||||
$this->socket->setToken($dto->access_code);
|
||||
$this->socket->setToken($formDatas['access_code']);
|
||||
$sns_entity = $this->socket->signup();
|
||||
// local db 사용와의 연결 확인
|
||||
$entity = $this->getEntity($sns_entity->getParent());
|
||||
if (!$entity instanceof UserEntity) {
|
||||
throw new PageNotFoundException("회원[{$sns_entity->getTitle()}]님은 아직 로컬사용자 연결이 이루어지지 않았습니다.");
|
||||
}
|
||||
return $this->login_process($entity);;
|
||||
return $entity;
|
||||
} catch (\Google_Service_Exception $e) {
|
||||
log_message('error', '구글 서비스 예외발생: ' . $e->getMessage());
|
||||
throw new PageNotFoundException("구글 로그인 중 오류가 발생했습니다. 다시 시도해 주세요.");
|
||||
@ -74,4 +53,13 @@ class GoogleService extends AuthService
|
||||
throw new PageNotFoundException("관리자에게 문의하시기 바랍니다.\n{$e->getMessage()}");
|
||||
}
|
||||
}
|
||||
public function login(mixed $dto): UserEntity
|
||||
{
|
||||
if (!$dto instanceof GoogleDTO) {
|
||||
throw new RuntimeException(__METHOD__ . "에서 오류발생: GoogleDTO만 사용하실수 있습니다");
|
||||
}
|
||||
return parent::login($dto);
|
||||
// DTO 객체를 배열로 변환하여 검증기에 전달
|
||||
$formDatas = (array) $dto;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,6 @@ use App\DTOs\Auth\LocalDTO;
|
||||
use App\Entities\UserEntity;
|
||||
use App\Forms\Auth\LocalForm;
|
||||
use App\Models\UserModel;
|
||||
use CodeIgniter\Validation\Exceptions\ValidationException;
|
||||
use RuntimeException;
|
||||
|
||||
class LocalService extends AuthService
|
||||
@ -16,6 +15,7 @@ class LocalService extends AuthService
|
||||
parent::__construct($model);
|
||||
$this->addClassPaths('Local');
|
||||
}
|
||||
|
||||
public function getFormService(): LocalForm
|
||||
{
|
||||
if ($this->formServiceInstance === null) {
|
||||
@ -25,42 +25,28 @@ class LocalService extends AuthService
|
||||
'title_field' => $this->model->getTitleField(),
|
||||
'table' => $this->model->getTable(),
|
||||
'useAutoIncrement' => $this->model->useAutoIncrement(),
|
||||
'class_path' => $this->getClassPaths(false)
|
||||
'class_path' => $this->getClassPaths(false),
|
||||
]);
|
||||
}
|
||||
return $this->formServiceInstance;
|
||||
}
|
||||
public function getFormFields(): array
|
||||
protected function login_process(array $formDatas): UserEntity
|
||||
{
|
||||
return ["id", "passwd",];
|
||||
}
|
||||
public function getFormFilters(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
public function getBatchjobButtons(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
//기본기능
|
||||
public function login(mixed $dto): UserEntity
|
||||
{
|
||||
if (!$dto instanceof LocalDTO) {
|
||||
throw new RuntimeException(__METHOD__ . "에서 오류발생: LcoalDTO만 사용하실수 있습니다");
|
||||
}
|
||||
// DTO 객체를 배열로 변환하여 검증기에 전달
|
||||
$formDatas = (array) $dto;
|
||||
if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) {
|
||||
// 검증 실패 시, ValidationException을 던집니다.
|
||||
throw new ValidationException(implode("\n", service('validation')->getErrors()));
|
||||
}
|
||||
$entity = $this->getEntity(['id' => $dto->id, 'status' => STATUS['AVAILABLE']], false);
|
||||
$entity = $this->getEntity(['id' => $formDatas['id'], 'status' => 'AVAILABLE'], true);
|
||||
if (!$entity instanceof UserEntity) {
|
||||
throw new \Exception("{$dto->id}에 대한 로그인 정보를 찾을수 없습니다.");
|
||||
throw new \Exception("{$formDatas['id']}에 대한 로그인 정보를 찾을수 없습니다.");
|
||||
}
|
||||
if (!password_verify($dto->passwd, $entity->getPassword())) {
|
||||
if (!password_verify($formDatas['passwd'], $entity->getPassword())) {
|
||||
throw new \Exception("암호가 맞지 않습니다.");
|
||||
}
|
||||
return $this->login_process($entity);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
public function login(object $dto): UserEntity
|
||||
{
|
||||
if (!$dto instanceof LocalDTO) {
|
||||
throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다.");
|
||||
}
|
||||
return parent::login($dto);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,10 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Entities\CommonEntity;
|
||||
use App\Models\CommonModel;
|
||||
use CodeIgniter\Validation\Exceptions\ValidationException;
|
||||
use RuntimeException;
|
||||
|
||||
abstract class CommonService
|
||||
{
|
||||
@ -96,6 +99,62 @@ abstract class CommonService
|
||||
}
|
||||
return $rules;
|
||||
}
|
||||
//CURD 결과처리용
|
||||
//DB 결과 처리 로직 통합 및 개선
|
||||
protected function handle_save_result(mixed $result, $entity): CommonEntity
|
||||
{
|
||||
if (!$result) {
|
||||
// static::class는 현재 호출된 자식 클래스 이름 반환
|
||||
throw new RuntimeException(static::class . "에서 {$entity->getTitle()} 등록/수정 중 DB 오류가 발생하였습니다.");
|
||||
}
|
||||
// 2. 최종 PK 값 결정 (insert/update 공통)
|
||||
$pkValue = $this->model->useAutoIncrement() && is_numeric($result) && (int)$result > 0
|
||||
? (int)$result
|
||||
: $entity->{$this->model->primaryKey};
|
||||
|
||||
if (empty($pkValue)) {
|
||||
throw new RuntimeException("{$entity->getTitle()} 저장 후 Primary Key를 확인할 수 없습니다.");
|
||||
}
|
||||
// 3. Entity 재조회 (수정 및 생성 모두 최신 DB 상태 반영)
|
||||
$savedEntity = $this->model->find($pkValue);
|
||||
if (!$savedEntity) {
|
||||
throw new RuntimeException("등록/수정된 데이터를 찾을 수 없습니다. (PK: {$pkValue})");
|
||||
}
|
||||
return $savedEntity;
|
||||
}
|
||||
//생성용
|
||||
abstract protected function create_process(array $formDatas): CommonEntity;
|
||||
public function create(object $dto): CommonEntity
|
||||
{
|
||||
$formDatas = (array) $dto;
|
||||
if (!service('validation')->setRules($this->getValidationRules(__FUNCTION__))->run($formDatas)) {
|
||||
throw new ValidationException(implode("\n", service('validation')->getErrors()));
|
||||
}
|
||||
$entity = $this->create_process($formDatas);
|
||||
$result = $this->model->insert($entity, $this->model->useAutoIncrement());
|
||||
return $this->handle_save_result($result, $entity);
|
||||
}
|
||||
//수정용
|
||||
abstract protected function modify_process(array $formDatas): array;
|
||||
public function modify(object $dto): CommonEntity
|
||||
{
|
||||
$formDatas = (array) $dto;
|
||||
if (!service('validation')->setRules($this->getValidationRules(__FUNCTION__))->run($formDatas)) {
|
||||
throw new ValidationException(implode("\n", service('validation')->getErrors()));
|
||||
}
|
||||
list($pk, $updateData) = $this->modify_process($formDatas);
|
||||
$entity = new ($this->model->returnType)($updateData); // 재조회에 필요한 PK를 얻기 위함
|
||||
$result = $this->model->update($pk, $updateData);
|
||||
return $this->handle_save_result($result, $entity);
|
||||
}
|
||||
protected function delete_process($uid): bool
|
||||
{
|
||||
return $this->model->delete($uid);
|
||||
}
|
||||
final public function delete($uid): bool
|
||||
{
|
||||
return $this->delete_process($uid);
|
||||
}
|
||||
//Index용
|
||||
final public function getTotalCount(): int
|
||||
{
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Services;
|
||||
|
||||
use App\DTOs\UserDTO;
|
||||
use App\Entities\CommonEntity;
|
||||
use App\Entities\UserEntity;
|
||||
use App\Forms\UserForm;
|
||||
use App\Helpers\UserHelper;
|
||||
@ -46,93 +47,53 @@ class UserService extends CommonService
|
||||
return $this->helperInstance;
|
||||
}
|
||||
//기본 기능부분
|
||||
public function create(UserDTO $dto): UserEntity
|
||||
protected function create_process(array $formDatas): UserEntity
|
||||
{
|
||||
// DTO 객체를 배열로 변환하여 검증기에 전달
|
||||
$formDatas = (array) $dto;
|
||||
// dd($formDatas);
|
||||
if (!service('validation')->setRules($this->getValidationRules(__FUNCTION__))->run($formDatas)) {
|
||||
throw new ValidationException(implode("\n", service('validation')->getErrors()));
|
||||
}
|
||||
$entity = new UserEntity($formDatas);
|
||||
$result = $this->model->insert($entity);
|
||||
if (!$result) {
|
||||
throw new \Exception("{$entity->getTitle()} 등록 중 DB 오류가 발생하였습니다.");
|
||||
}
|
||||
// 💡 PK 타입에 따른 최종 Entity 반환 로직 분기
|
||||
if ($this->model->useAutoIncrement) { //정수 PK인 경우
|
||||
$savedEntity = $this->model->find($result);
|
||||
} else { //문자열 PK인 경우
|
||||
$pkValue = $entity->{$this->model->primaryKey};
|
||||
$savedEntity = $this->model->find($pkValue);
|
||||
}
|
||||
if (!$savedEntity instanceof UserEntity) {
|
||||
throw new \Exception("등록된 데이터를 찾을 수 없습니다.");
|
||||
}
|
||||
return $savedEntity;
|
||||
return new UserEntity($formDatas);
|
||||
}
|
||||
public function modify(UserDTO $dto): UserEntity
|
||||
public function create(object $dto): UserEntity
|
||||
{
|
||||
// DTO 객체를 배열로 변환하여 검증기에 전달
|
||||
$formDatas = (array) $dto;
|
||||
// dd($formDatas);
|
||||
if (!service('validation')->setRules($this->getValidationRules(__FUNCTION__))->run($formDatas)) {
|
||||
throw new ValidationException(implode("\n", service('validation')->getErrors()));
|
||||
if (!$dto instanceof UserDTO) {
|
||||
throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다.");
|
||||
}
|
||||
$entity = new UserEntity($formDatas);
|
||||
$result = $this->model->update($entity->getPK(), $formDatas);
|
||||
if (!$result) {
|
||||
throw new \Exception("{$entity->getTitle()} 등록 중 DB 오류가 발생하였습니다.");
|
||||
}
|
||||
// 💡 PK 타입에 따른 최종 Entity 반환 로직 분기
|
||||
if ($this->model->useAutoIncrement) { //정수 PK인 경우
|
||||
$savedEntity = $this->model->find($result);
|
||||
} else { //문자열 PK인 경우
|
||||
$pkValue = $entity->{$this->model->primaryKey};
|
||||
$savedEntity = $this->model->find($pkValue);
|
||||
}
|
||||
if (!$savedEntity instanceof UserEntity) {
|
||||
throw new \Exception("등록된 데이터를 찾을 수 없습니다.");
|
||||
}
|
||||
return $savedEntity;
|
||||
return parent::create($dto);
|
||||
}
|
||||
protected function modify_process(array $formDatas): array
|
||||
{
|
||||
// DTO에 PK가 포함되어 있다고 가정. 필요 시 데이터 가공
|
||||
return [
|
||||
$formDatas[$this->model->primaryKey], // PK
|
||||
$formDatas // Update Data
|
||||
];
|
||||
}
|
||||
public function modify(object $dto): UserEntity
|
||||
{
|
||||
if (!$dto instanceof UserDTO) {
|
||||
throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다.");
|
||||
}
|
||||
return parent::modify($dto);
|
||||
}
|
||||
//List 검색용
|
||||
//FormFilter 조건절 처리
|
||||
public function index_condition_filterField(string $field, mixed $filter_value): void
|
||||
{
|
||||
switch ($field) {
|
||||
case 'role':
|
||||
$where = "FIND_IN_SET(" . $this->model->escape($filter_value) . ", {$this->model->getTable()}.{$field}) > 0";
|
||||
//FIND_IN_SET()은 MySQL 함수이므로 CodeIgniter가 이를 일반 컬럼명으로 착각하고 escape하게 되면 오류가 발생합니다. 따라서 ->where($sql, null, false)로 명시하여 escape를 꺼줘야 정상 작동
|
||||
$this->model->where($where, null, false);
|
||||
break;
|
||||
default:
|
||||
parent::index_condition_filterField($field, $filter_value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//검색어조건절처리
|
||||
public function index_condition_filterWord(string $word): void
|
||||
{
|
||||
$this->model->orLike($this->model->getTable() . '.id', $word, 'both');
|
||||
$this->model->orLike($this->model->getTable() . "." . $this->model->getTitleField(), $word, 'both');
|
||||
$this->model->orLike($this->model->getTable() . '.email', $word, 'both');
|
||||
parent::index_condition_filterWord($word);
|
||||
}
|
||||
// protected function modify_process(mixed $entity, array $formDatas): UserEntity
|
||||
// {
|
||||
// // die(var_export($formDatas, true));
|
||||
// //암호를 입력하지 않았을시는 변경하기 않게 하기위함
|
||||
// if (isset($formDatas['passwd']) && $formDatas['passwd'] == "") {
|
||||
// unset($formDatas['passwd']);
|
||||
// unset($formDatas['confirmpassword']);
|
||||
// }
|
||||
// //Role을 지정이 있을경우에만 , toggle이나 batcjhjob에서는 없을수도 있으므로
|
||||
// if (isset($formDatas['role'])) {
|
||||
// $formDatas['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $formDatas['role']);
|
||||
// }
|
||||
// // die(var_export($formDatas, true));
|
||||
// $entity = parent::modify_process($entity, $formDatas);
|
||||
// return $entity;
|
||||
// }
|
||||
// //List 검색용
|
||||
// //FormFilter 조건절 처리
|
||||
// public function index_condition_filterField(string $field, mixed $filter_value): void
|
||||
// {
|
||||
// switch ($field) {
|
||||
// case 'role':
|
||||
// $where = "FIND_IN_SET(" . $this->model->escape($filter_value) . ", {$this->model->getTable()}.{$field}) > 0";
|
||||
// //FIND_IN_SET()은 MySQL 함수이므로 CodeIgniter가 이를 일반 컬럼명으로 착각하고 escape하게 되면 오류가 발생합니다. 따라서 ->where($sql, null, false)로 명시하여 escape를 꺼줘야 정상 작동
|
||||
// $this->model->where($where, null, false);
|
||||
// break;
|
||||
// default:
|
||||
// parent::index_condition_filterField($field, $filter_value);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// //검색어조건절처리
|
||||
// public function index_condition_filterWord(string $word): void
|
||||
// {
|
||||
// $this->model->orLike($this->model->getTable() . '.id', $word, 'both');
|
||||
// $this->model->orLike($this->model->getTable() . "." . $this->model->getTitleField(), $word, 'both');
|
||||
// $this->model->orLike($this->model->getTable() . '.email', $word, 'both');
|
||||
// parent::index_condition_filterWord($word);
|
||||
// }
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user