fix: 사원 등록 시 이메일 중복 체크 및 user_id 충돌 방지
- 이메일 중복 체크 추가 (삭제된 사용자 포함) - generateUniqueUserId() 메서드 추가 (중복 시 최대 10회 재시도) - email_already_exists 에러 메시지 추가 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -98,14 +98,23 @@ public function store(array $data): TenantUserProfile
|
|||||||
$tenantId = $this->tenantId();
|
$tenantId = $this->tenantId();
|
||||||
$userId = $this->apiUserId();
|
$userId = $this->apiUserId();
|
||||||
|
|
||||||
return DB::transaction(function () use ($data, $tenantId, $userId) {
|
// 1. 이메일 중복 체크 (전역 유니크)
|
||||||
// 1. 비밀번호 결정: password가 있으면 시스템 계정 생성
|
$existingUser = User::withTrashed()->where('email', $data['email'])->first();
|
||||||
|
if ($existingUser) {
|
||||||
|
throw new \InvalidArgumentException(__('error.email_already_exists'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. user_id 중복 체크 및 유니크 ID 생성
|
||||||
|
$userIdValue = $data['user_id'] ?? $this->generateUniqueUserId($data['email']);
|
||||||
|
|
||||||
|
return DB::transaction(function () use ($data, $tenantId, $userId, $userIdValue) {
|
||||||
|
// 3. 비밀번호 결정: password가 있으면 시스템 계정 생성
|
||||||
// User 모델에 'password' => 'hashed' 캐스트가 있으므로 Hash::make() 불필요
|
// User 모델에 'password' => 'hashed' 캐스트가 있으므로 Hash::make() 불필요
|
||||||
$password = ! empty($data['password']) ? $data['password'] : null;
|
$password = ! empty($data['password']) ? $data['password'] : null;
|
||||||
|
|
||||||
// 2. users 테이블에 사용자 생성
|
// 4. users 테이블에 사용자 생성
|
||||||
$user = User::create([
|
$user = User::create([
|
||||||
'user_id' => $data['user_id'] ?? $this->generateUserId($data['email']),
|
'user_id' => $userIdValue,
|
||||||
'name' => $data['name'],
|
'name' => $data['name'],
|
||||||
'email' => $data['email'],
|
'email' => $data['email'],
|
||||||
'phone' => $data['phone'] ?? null,
|
'phone' => $data['phone'] ?? null,
|
||||||
@@ -377,13 +386,26 @@ public function revokeAccount(int $id): TenantUserProfile
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 사용자 ID 자동 생성
|
* 유니크한 사용자 ID 자동 생성
|
||||||
|
* 중복 시 최대 10회까지 재시도
|
||||||
*/
|
*/
|
||||||
private function generateUserId(string $email): string
|
private function generateUniqueUserId(string $email): string
|
||||||
{
|
{
|
||||||
$prefix = explode('@', $email)[0];
|
$prefix = explode('@', $email)[0];
|
||||||
$suffix = Str::random(4);
|
$prefix = strtolower(preg_replace('/[^a-zA-Z0-9]/', '', $prefix));
|
||||||
|
|
||||||
return strtolower($prefix.'_'.$suffix);
|
$maxAttempts = 10;
|
||||||
|
for ($i = 0; $i < $maxAttempts; $i++) {
|
||||||
|
$suffix = Str::random(6); // 4자리 → 6자리로 증가
|
||||||
|
$userId = $prefix.'_'.$suffix;
|
||||||
|
|
||||||
|
// 중복 체크 (삭제된 사용자 포함)
|
||||||
|
if (! User::withTrashed()->where('user_id', $userId)->exists()) {
|
||||||
|
return $userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 최대 시도 후에도 실패 시 타임스탬프 추가
|
||||||
|
return $prefix.'_'.time().'_'.Str::random(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
// 검증/파라미터
|
// 검증/파라미터
|
||||||
'validation_failed' => '요청 데이터 검증에 실패했습니다.', // 422
|
'validation_failed' => '요청 데이터 검증에 실패했습니다.', // 422
|
||||||
'missing_parameter' => '필수 파라미터가 누락되었습니다.', // 400
|
'missing_parameter' => '필수 파라미터가 누락되었습니다.', // 400
|
||||||
|
'email_already_exists' => '이미 사용 중인 이메일 주소입니다.', // 400
|
||||||
'business_num_format' => '사업자등록번호 형식이 올바르지 않습니다 (000-00-00000)',
|
'business_num_format' => '사업자등록번호 형식이 올바르지 않습니다 (000-00-00000)',
|
||||||
'business_num_duplicate_active' => '이미 등록된 사업자등록번호입니다 (정식 서비스 업체)',
|
'business_num_duplicate_active' => '이미 등록된 사업자등록번호입니다 (정식 서비스 업체)',
|
||||||
'user_id_format' => '아이디는 영문, 숫자, _, - 만 사용할 수 있습니다',
|
'user_id_format' => '아이디는 영문, 숫자, _, - 만 사용할 수 있습니다',
|
||||||
|
|||||||
Reference in New Issue
Block a user