Skip to main content

권한 시스템

📝 초안 (Draft)

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

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

개요

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) ← 기본 권한

권한 분류 (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) {
// 로직 중복, 유지보수 어려움
}

관련 문서