chore: [env] .env.example 업데이트 및 .gitignore 정리

- .env.example을 SAM 프로젝트 실제 키 구조로 업데이트
- .gitignore에 !.env.example 예외 추가
- GCS_* 중복 키 제거, Gemini/Claude/Vertex 키 섹션 추가
This commit is contained in:
김보곤
2026-02-23 10:17:37 +09:00
parent 3ae3a1dcda
commit 240199af9d
51 changed files with 623 additions and 2726 deletions

View File

@@ -3,7 +3,8 @@
namespace App\Services\Authz;
use App\Models\Members\User;
use App\Models\Permissions\Role;
use Illuminate\Support\Facades\Validator;
use Spatie\Permission\Models\Role;
use Spatie\Permission\PermissionRegistrar;
class UserRoleService
@@ -16,13 +17,6 @@ protected static function setTeam(int $tenantId): void
app(PermissionRegistrar::class)->setPermissionsTeamId($tenantId);
}
/** 권한 캐시 무효화 */
protected static function invalidateCache(int $tenantId): void
{
AccessService::bumpVersion($tenantId);
app(PermissionRegistrar::class)->forgetCachedPermissions();
}
/** 유저 로드 (존재 체크) */
protected static function loadUserOrError(int $userId): ?User
{
@@ -60,13 +54,14 @@ protected static function resolveRoleNames(int $tenantId, array $params): array
// 정제
$names = array_values(array_unique(array_filter($names)));
// 존재 확인
// 존재 확인(필요시 에러 처리 확장 가능)
if (! empty($names)) {
Role::query()
$count = Role::query()
->where('tenant_id', $tenantId)
->where('guard_name', self::$guard)
->whereIn('name', $names)
->count();
// if ($count !== count($names)) { ... 필요시 상세 에러 반환 }
}
return $names;
@@ -79,11 +74,12 @@ public static function list(int $userId)
$user = self::loadUserOrError($userId);
if (! $user) {
return ['error' => __('error.role.user_not_found'), 'code' => 404];
return ['error' => '사용자를 찾을 수 없습니다.', 'code' => 404];
}
self::setTeam($tenantId);
// 현재 테넌트의 역할만
$builder = $user->roles()
->where('roles.tenant_id', $tenantId)
->where('roles.guard_name', self::$guard)
@@ -100,19 +96,30 @@ public static function grant(int $userId, array $params = [])
$user = self::loadUserOrError($userId);
if (! $user) {
return ['error' => __('error.role.user_not_found'), 'code' => 404];
return ['error' => '사용자를 찾을 수 없습니다.', 'code' => 404];
}
$v = Validator::make($params, [
'role_names' => 'sometimes|array',
'role_names.*' => 'string|min:1',
'role_ids' => 'sometimes|array',
'role_ids.*' => 'integer|min:1',
]);
if ($v->fails()) {
return ['error' => $v->errors()->first(), 'code' => 422];
}
if (empty($params['role_names']) && empty($params['role_ids'])) {
return ['error' => 'role_names 또는 role_ids 중 하나는 필요합니다.', 'code' => 422];
}
self::setTeam($tenantId);
$names = self::resolveRoleNames($tenantId, $params);
if (empty($names)) {
return ['error' => __('error.role.no_valid_roles'), 'code' => 422];
return ['error' => '유효한 역할이 없습니다.', 'code' => 422];
}
$user->assignRole($names);
self::invalidateCache($tenantId);
$user->assignRole($names); // teams 컨텍스트 적용됨
return 'success';
}
@@ -124,19 +131,30 @@ public static function revoke(int $userId, array $params = [])
$user = self::loadUserOrError($userId);
if (! $user) {
return ['error' => __('error.role.user_not_found'), 'code' => 404];
return ['error' => '사용자를 찾을 수 없습니다.', 'code' => 404];
}
$v = Validator::make($params, [
'role_names' => 'sometimes|array',
'role_names.*' => 'string|min:1',
'role_ids' => 'sometimes|array',
'role_ids.*' => 'integer|min:1',
]);
if ($v->fails()) {
return ['error' => $v->errors()->first(), 'code' => 422];
}
if (empty($params['role_names']) && empty($params['role_ids'])) {
return ['error' => 'role_names 또는 role_ids 중 하나는 필요합니다.', 'code' => 422];
}
self::setTeam($tenantId);
$names = self::resolveRoleNames($tenantId, $params);
if (empty($names)) {
return ['error' => __('error.role.no_valid_roles'), 'code' => 422];
return ['error' => '유효한 역할이 없습니다.', 'code' => 422];
}
$user->removeRole($names);
self::invalidateCache($tenantId);
$user->removeRole($names); // 배열 허용
return 'success';
}
@@ -148,20 +166,32 @@ public static function sync(int $userId, array $params = [])
$user = self::loadUserOrError($userId);
if (! $user) {
return ['error' => __('error.role.user_not_found'), 'code' => 404];
return ['error' => '사용자를 찾을 수 없습니다.', 'code' => 404];
}
$v = Validator::make($params, [
'role_names' => 'sometimes|array',
'role_names.*' => 'string|min:1',
'role_ids' => 'sometimes|array',
'role_ids.*' => 'integer|min:1',
]);
if ($v->fails()) {
return ['error' => $v->errors()->first(), 'code' => 422];
}
if (empty($params['role_names']) && empty($params['role_ids'])) {
return ['error' => 'role_names 또는 role_ids 중 하나는 필요합니다.', 'code' => 422];
}
self::setTeam($tenantId);
$names = self::resolveRoleNames($tenantId, $params);
if (empty($names)) {
return ['error' => __('error.role.no_valid_roles'), 'code' => 422];
// 정책상 빈 목록 sync 허용 시: $user->syncRoles([]) 로 전부 제거 가능
return ['error' => '유효한 역할이 없습니다.', 'code' => 422];
}
$user->syncRoles($names);
self::invalidateCache($tenantId);
return 'success';
}
}