본문으로 건너뛰기

Tenant 패널 (Level 2)

📝 초안 (Draft)

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

Tenant Admin 전용 패널 기능을 설명합니다.

개요​

Tenant 패널은 **Level 2 (Tenant Admin)**을 위한 관리 패널입니다. 테넌트(고객사) 내의 조직 구조, 사용자, Guardian 관계 등을 관리합니다.

접근 권한​

항목값
권한 레벨Level 2 (Tenant Admin)
기본 경로/tenant
환경변수PANEL_PATH_TENANT
접근 가능자Level 0, 1, 2

담당 범위​

Tenant Admin은 자신의 테넌트 내에서만 권한을 가집니다:

Tenant A (담당)
├── Organization 1 ✅ 관리 가능
│ ├── Workspace 1 ✅
│ └── Workspace 2 ✅
├── Organization 2 ✅ 관리 가능
│ └── Workspace 3 ✅
└── 모든 사용자 ✅ 관리 가능

Tenant B (타 테넌트)
└── 모든 데이터 ❌ 접근 불가 (RLS 격리)

범용 UX 기능​

기능설명
brandName좌상단에 테넌트 이름 표시 (logo_url 등록 시 로고 표시)
tenantMenu테넌트 선택 드롭다운 숨김 (URL로 결정)
패널간 네비게이션우상단 메뉴에서 Platform/SaaS 패널로 이동 (L0/L1만)
SafeDeleteAction모든 삭제에 "DELETE {대상명}" 입력 확인
homeUrl좌상단 로고 클릭 시 현재 테넌트 대시보드로 이동

주요 기능​

1. 조직(Organization) 관리​

테넌트 내의 조직 구조를 관리합니다. 조직은 계층 구조를 가질 수 있습니다.

OrganizationResource 주요 필드:

필드설명예시
name조직명"영업부"
code조직 코드"SALES-001"
type조직 유형headquarters, division, department, team
parent_id상위 조직null (최상위) 또는 조직 ID
org_level조직 레벨1, 2, 3...
is_active활성화 여부true/false

조직 유형:

유형설명색상
headquarters본사빨강
division사업부주황
department부서파랑
team팀초록

2. Guardian 관계 관리​

Guardian 확장이 활성화된 경우, 보호자-피보호자 관계를 관리합니다.

GuardianRelationshipResource 기능:

  • 관계 생성 (학부모-학생, 담당교사-학생 등)
  • 승인 대기 목록 확인
  • 승인/거부 액션
액션설명
ApproveAction관계 요청 승인 (pending → approved)
RejectAction관계 요청 거부 (pending → rejected)
// GuardianRelationshipResource.php
use App\Core\Extensions\Guardian\Filament\Actions\ApproveAction;
use App\Core\Extensions\Guardian\Filament\Actions\RejectAction;

->recordActions([
ApproveAction::make(),
RejectAction::make(),
EditAction::make(),
])

3. 사용자 관리​

테넌트 내 모든 레벨의 사용자를 관리합니다.

관리 대상레벨설명
Organization AdminLevel 3조직 관리자 배정
Workspace AdminLevel 4워크스페이스 관리자 배정
Group LeaderLevel 5그룹 리더 배정
MemberLevel 6일반 회원 관리

4. 감사 로그​

테넌트 내의 감사 로그를 조회합니다. (플랫폼 전체가 아닌 테넌트 범위)

// TenantAuditLogResource.php
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
->where('tenant_id', auth()->user()->tenant_id);
}

파일 구조​

app/Filament/Tenant/
├── Resources/
│ ├── OrganizationResource.php
│ │ └── Pages/
│ │ ├── ListOrganizations.php
│ │ ├── CreateOrganization.php
│ │ └── EditOrganization.php
│ │
│ ├── GuardianRelationshipResource.php
│ │ └── Pages/
│ │ ├── ListGuardianRelationships.php
│ │ ├── CreateGuardianRelationship.php
│ │ └── EditGuardianRelationship.php
│ │
│ └── AuditLogResource.php
│ └── Pages/
│ ├── ListAuditLogs.php
│ └── ViewAuditLog.php
│
├── Pages/
│ └── Dashboard.php
│
└── Widgets/
├── OrganizationTreeWidget.php
└── GuardianPendingWidget.php

PanelProvider 설정​

// app/Providers/Filament/TenantPanelProvider.php

class TenantPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
return $panel
->id('tenant')
->path(env('PANEL_PATH_TENANT', 'tenant'))
->login()
->colors(['primary' => Color::Blue])
->tenant(Tenant::class) // 멀티테넌트 활성화
->discoverResources(
in: app_path('Filament/Tenant/Resources'),
for: 'App\Filament\Tenant\Resources'
)
->authMiddleware([
Authenticate::class,
EnsureUserLevel::class.':0,1,2', // Level 0-2 접근
]);
}
}

RLS 데이터 격리​

Tenant 패널의 모든 리소스는 **RLS(Row Level Security)**로 자동 격리됩니다.

HasTenantBasedAuthorization Trait​

// OrganizationResource.php
use App\Core\Base\Permission\Filament\Traits\HasTenantBasedAuthorization;

class OrganizationResource extends Resource
{
use HasTenantBasedAuthorization;

// 자동으로 tenant_id 필터링 적용
}

자동 필터링​

public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
->where('tenant_id', auth()->user()->tenant_id);
}
RLS 보장

PostgreSQL RLS 정책으로 DB 레벨에서도 격리가 보장됩니다. SQL Injection 공격으로도 다른 테넌트 데이터에 접근할 수 없습니다.


Guardian 확장 통합​

Guardian 확장이 활성화되면 Tenant 패널에 Guardian 관련 기능이 추가됩니다.

활성화 확인​

// config/core.php
'extensions' => [
'guardian' => env('CORE_GUARDIAN_ENABLED', false),
],

조건부 네비게이션​

// GuardianRelationshipResource.php
public static function shouldRegisterNavigation(): bool
{
return config('core.extensions.guardian', false);
}

관련 문서​