Skip to main content

권한 시스템

📝 초안 (Draft)

이 문서는 검토 중입니다. 내용이 변경될 수 있습니다.

Multi-SaaS Kit의 권한 시스템 (Level 0~6, ADR-058) 개념과 사용법을 설명합니다.

계층 구조 모델은 별도 문서

이 페이지는 권한의 사용법(Policy / Gate / Middleware / Filament)을 다룹니다. 권한 계층 구조 모델(고정 백본 + organizations 가변 트리, depth 무제한)은 → 권한 계층 을 참조하세요.

개요​

Multi-SaaS Kit은 **권한 시스템 (Level 0~6, ADR-058)**을 사용합니다. 숫자가 낮을수록 높은 권한을 가지며, 상위 권한은 하위 권한의 모든 기능에 접근할 수 있습니다.

Level 0 (Platform Admin)     ← 최고 권한
↓
Level 1 (SaaS Admin)
↓
Level 2 (Tenant Admin)
↓
Level 3 (Organization Admin)
↓
Level 4 (Workspace Admin)
↓
Level 5 (Group Leader)
↓
Level 6 (Member) ← 기본 권한

※ 위 일렬 표현은 권한 분류(users.level 06, 고정)입니다. 실제 조직 구조는 Level 02 고정 백본(별도 테이블) + Level 3~5 organizations 자기참조 트리(depth 무제한, org_level 라벨) + Level 6 단말로 이루어집니다. 자세히는 권한 계층 참조.

권한 분류 (Level 0~6) 테이블​

Level명칭범위주요 역할
0Platform Admin전체 플랫폼시스템 운영, 모든 데이터 접근
1SaaS Admin전체 플랫폼SaaS 제품 관리, 테넌트 생성
2Tenant Admin테넌트 내고객사 관리자, 조직 관리
3Organization Admin조직 내조직/부서 관리
4Workspace Admin워크스페이스 내프로젝트/작업 공간 관리
5Group Leader그룹 내팀/그룹 리더
6Member본인일반 사용자

레벨별 상세 설명​

Level 0: Platform Admin​

플랫폼 운영자로서 시스템 전체를 관리합니다.

권한설명
전체 데이터 접근모든 테넌트의 데이터 조회/수정
테넌트 격리 우회RLS 정책 우회 가능
시스템 설정플랫폼 전체 설정 변경
사용자 전환모든 사용자로 전환(Impersonate)
// Level 0 확인
if ($user->isPlatformAdmin()) {
// 플랫폼 전체 관리 기능
}

Level 1: SaaS Admin​

SaaS 서비스 관리자로서 여러 테넌트를 관리합니다.

권한설명
테넌트 관리테넌트 생성/수정/삭제
테넌트 격리 우회RLS 정책 우회 가능
제품 설정SaaS 제품별 설정
사용자 전환Level 2 이하 사용자로 전환
// Level 1 이상 확인
if ($user->isSaasAdmin()) {
// SaaS 관리 기능
}

Level 2: Tenant Admin​

테넌트(고객사) 관리자로서 자신의 테넌트를 관리합니다.

권한설명
조직 관리테넌트 내 조직 생성/관리
사용자 관리테넌트 내 사용자 초대/관리
설정 관리테넌트 설정 변경
데이터 접근자신의 테넌트 데이터만
// Level 2 이상 확인
if ($user->isTenantAdmin()) {
// 테넌트 관리 기능
}
테넌트 격리

Level 2 이하는 자신의 테넌트 데이터만 접근할 수 있습니다. RLS(Row-Level Security)가 자동으로 적용됩니다.

Level 3-6: 테넌트 내 권한​

Level명칭관리 범위
3Organization Admin조직/부서
4Workspace Admin프로젝트/작업공간
5Group Leader팀/그룹
6Member본인 데이터

권한 상속 규칙​

상위 권한은 하위 권한을 포함​

Level 0은 Level 1, 2, 3, 4, 5, 6의 모든 권한을 포함
Level 1은 Level 2, 3, 4, 5, 6의 모든 권한을 포함
...

코드에서 확인​

// 특정 레벨 이상인지 확인
$user->hasLevelAtLeast(UserLevel::TENANT_ADMIN); // Level 2 이상

// 정확히 특정 레벨인지 확인
$user->hasLevelExact(UserLevel::TENANT_ADMIN); // 정확히 Level 2

// 레벨 범위 확인
$user->hasLevelBetween(
UserLevel::TENANT_ADMIN, // min: Level 2
UserLevel::GROUP_LEADER // max: Level 5
);

사용자 관리 권한​

// 대상 사용자를 관리할 수 있는지 확인
if ($currentUser->canManageUser($targetUser)) {
// 자신보다 하위 레벨만 관리 가능
// Tenant Admin 이하는 같은 테넌트 내에서만 관리 가능
}

권한 레벨 분류​

플랫폼 레벨 (Level 0-1)​

테넌트 격리를 우회할 수 있는 특권 레벨입니다.

// 플랫폼 레벨인지 확인
if ($user->getUserLevel()->isPlatformLevel()) {
// 모든 테넌트 데이터 접근 가능
}

// 테넌트 격리 우회 가능한지 확인
if ($user->canBypassTenantIsolation()) {
// RLS 우회
}

테넌트 레벨 (Level 2-6)​

자신의 테넌트 내에서만 활동하는 레벨입니다.

// 테넌트 레벨인지 확인
if ($user->getUserLevel()->isTenantLevel()) {
// 자신의 테넌트 데이터만 접근
}

구현 예제​

Policy 정의​

namespace App\Policies;

use App\Models\User;
use App\Models\Organization;
use App\Core\Base\Permission\Enums\UserLevel;

class OrganizationPolicy
{
/**
* 조직 생성 권한 (Level 2 이상)
*/
public function create(User $user): bool
{
return $user->hasLevelAtLeast(UserLevel::TENANT_ADMIN);
}

/**
* 조직 수정 권한
*/
public function update(User $user, Organization $org): bool
{
// Platform/SaaS Admin은 모든 조직 수정 가능
if ($user->isSaasAdmin()) {
return true;
}

// Tenant Admin은 자신의 테넌트 조직만
if ($user->isTenantAdmin()) {
return $user->tenant_id === $org->tenant_id;
}

// Org Admin은 자신의 조직만
return $user->isOrgAdmin()
&& $user->organization_id === $org->id;
}

/**
* 조직 삭제 권한 (Level 2 이상)
*/
public function delete(User $user, Organization $org): bool
{
return $this->update($user, $org)
&& $user->hasLevelAtLeast(UserLevel::TENANT_ADMIN);
}
}

Gate 정의​

// AppServiceProvider.php

use Illuminate\Support\Facades\Gate;
use App\Core\Base\Permission\Enums\UserLevel;

public function boot(): void
{
// 관리자 접근 Gate
Gate::define('access-admin', function ($user) {
return $user->hasLevelAtLeast(UserLevel::TENANT_ADMIN);
});

// 시스템 설정 Gate
Gate::define('manage-system', function ($user) {
return $user->isPlatformAdmin();
});

// 사용자 관리 Gate
Gate::define('manage-users', function ($user, $target = null) {
if ($target) {
return $user->canManageUser($target);
}
return $user->hasLevelAtLeast(UserLevel::GROUP_LEADER);
});
}

Middleware 적용​

라우트에서 특정 레벨만 접근을 허용합니다.

use App\Core\Base\Permission\Middleware\EnsureUserLevel;

// 단일 레벨 허용
Route::middleware(['auth', EnsureUserLevel::class.':0'])
->prefix('platform')
->group(function () {
// Platform Admin 전용
});

// 여러 레벨 허용
Route::middleware(['auth', EnsureUserLevel::class.':0,1,2'])
->prefix('admin')
->group(function () {
// Level 0, 1, 2 접근 가능
});

// 또는 문자열로
Route::middleware(['auth', 'level:0,1'])
->group(function () {
// Platform/SaaS Admin만
});

Filament 패널 통합​

각 패널별로 접근 가능한 레벨을 지정합니다.

// app/Providers/Filament/PlatformPanelProvider.php

use App\Core\Base\Permission\Middleware\EnsureUserLevel;

public function panel(Panel $panel): Panel
{
return $panel
->id('platform')
->path(env('PANEL_PATH_PLATFORM', 'platform'))
->authMiddleware([
Authenticate::class,
EnsureUserLevel::class.':0', // Level 0만
])
// ...
}
// app/Providers/Filament/TenantPanelProvider.php

public function panel(Panel $panel): Panel
{
return $panel
->id('tenant')
->path(env('PANEL_PATH_TENANT', 'tenant'))
->authMiddleware([
Authenticate::class,
EnsureUserLevel::class.':0,1,2', // Level 0-2
])
// ...
}

Filament Resource 권한​

namespace App\Filament\Platform\Resources;

use Filament\Resources\Resource;
use App\Core\Base\Permission\Enums\UserLevel;

class UserResource extends Resource
{
public static function canViewAny(): bool
{
return auth()->user()->hasLevelAtLeast(UserLevel::SAAS_ADMIN);
}

public static function canCreate(): bool
{
return auth()->user()->hasLevelAtLeast(UserLevel::SAAS_ADMIN);
}

public static function canEdit($record): bool
{
return auth()->user()->canManageUser($record);
}

public static function canDelete($record): bool
{
return auth()->user()->canManageUser($record)
&& auth()->user()->hasLevelAtLeast(UserLevel::TENANT_ADMIN);
}
}

레벨 라벨 커스터마이징​

config에서 설정​

// config/core.php

return [
'permission' => [
'levels' => [
0 => 'Platform Admin',
1 => 'SaaS Admin',
2 => 'Tenant Admin',
3 => 'Organization Admin',
4 => 'Workspace Admin',
5 => 'Group Leader',
6 => 'Member',
],
],
];

SaaS 제품별 커스터마이징​

동일한 레벨이라도 SaaS 제품에 따라 다른 라벨을 사용할 수 있습니다.

// 교육 플랫폼
Level 2: "학교 관리자"
Level 5: "담임 선생님"
Level 6: "학생"

// 의료 플랫폼
Level 2: "병원 관리자"
Level 5: "의사"
Level 6: "환자"

모범 사례​

1. 최소 권한 원칙​

필요한 최소한의 권한만 부여합니다.

// ✅ 좋은 예: 정확한 레벨 확인
if ($user->hasLevelAtLeast(UserLevel::TENANT_ADMIN)) {
// 필요한 최소 레벨
}

// ❌ 나쁜 예: 불필요하게 높은 권한 요구
if ($user->isPlatformAdmin()) {
// 모든 기능에 Platform Admin 요구
}

2. 테넌트 컨텍스트 확인​

테넌트 레벨에서는 항상 테넌트 소속을 확인합니다.

// ✅ 좋은 예: 테넌트 소속 확인
if ($user->isTenantAdmin() && $user->tenant_id === $resource->tenant_id) {
// 자신의 테넌트 리소스만
}

// ❌ 나쁜 예: 테넌트 확인 누락
if ($user->isTenantAdmin()) {
// 다른 테넌트 데이터 접근 가능 (보안 위험)
}

3. Policy 사용 권장​

복잡한 권한 로직은 Policy에 캡슐화합니다.

// ✅ 좋은 예: Policy 사용
$this->authorize('update', $organization);

// ❌ 나쁜 예: 컨트롤러에 권한 로직 직접 작성
if ($user->level <= 2 && $user->tenant_id === $org->tenant_id) {
// 로직 중복, 유지보수 어려움
}

관련 문서​