chore: 통합 테스트 환경과 보고서 리모트 구성
This commit is contained in:
8
lib/core/network/api_routes.dart
Normal file
8
lib/core/network/api_routes.dart
Normal file
@@ -0,0 +1,8 @@
|
||||
/// API 경로 상수 모음
|
||||
/// - 버전 prefix 등을 중앙에서 관리해 중복을 방지한다.
|
||||
class ApiRoutes {
|
||||
const ApiRoutes._();
|
||||
|
||||
/// API v1 prefix
|
||||
static const apiV1 = '/api/v1';
|
||||
}
|
||||
116
lib/core/permissions/permission_resources.dart
Normal file
116
lib/core/permissions/permission_resources.dart
Normal file
@@ -0,0 +1,116 @@
|
||||
/// 권한 검사에 사용하는 리소스 경로 상수를 정의하고 정규화 유틸을 제공한다.
|
||||
///
|
||||
/// - UI 라우트 경로(`/inventory/inbound` 등)를 서버 표준 경로(`/stock-transactions`)
|
||||
/// 로 변환해 [PermissionManager]와 환경 설정이 동일한 키를 사용하도록 맞춘다.
|
||||
class PermissionResources {
|
||||
const PermissionResources._();
|
||||
|
||||
static const String dashboard = '/dashboard';
|
||||
static const String stockTransactions = '/stock-transactions';
|
||||
static const String approvals = '/approvals';
|
||||
static const String approvalSteps = '/approval-steps';
|
||||
static const String approvalHistories = '/approval-histories';
|
||||
static const String approvalTemplates = '/approval-templates';
|
||||
static const String groupMenuPermissions = '/group-menu-permissions';
|
||||
static const String vendors = '/vendors';
|
||||
static const String products = '/products';
|
||||
static const String warehouses = '/warehouses';
|
||||
static const String customers = '/customers';
|
||||
static const String users = '/users';
|
||||
static const String groups = '/groups';
|
||||
static const String menus = '/menus';
|
||||
static const String postalSearch = '/zipcodes';
|
||||
static const String reports = '/reports';
|
||||
static const String reportsTransactions = '/reports/transactions';
|
||||
static const String reportsApprovals = '/reports/approvals';
|
||||
|
||||
/// 라우트/엔드포인트 별칭을 표준 경로로 매핑한 테이블.
|
||||
static const Map<String, String> _aliases = {
|
||||
'/dashboard': dashboard,
|
||||
'/inventory': stockTransactions,
|
||||
'/inventory/inbound': stockTransactions,
|
||||
'/inventory/outbound': stockTransactions,
|
||||
'/inventory/rental': stockTransactions,
|
||||
'/approvals/requests': approvals,
|
||||
'/approvals': approvals,
|
||||
'/approvals/steps': approvalSteps,
|
||||
'/approval-steps': approvalSteps,
|
||||
'/approvals/history': approvalHistories,
|
||||
'/approvals/histories': approvalHistories,
|
||||
'/approval-histories': approvalHistories,
|
||||
'/approvals/templates': approvalTemplates,
|
||||
'/approval-templates': approvalTemplates,
|
||||
'/masters/group-permissions': groupMenuPermissions,
|
||||
'/group-menu-permissions': groupMenuPermissions,
|
||||
'/masters/vendors': vendors,
|
||||
'/vendors': vendors,
|
||||
'/masters/products': products,
|
||||
'/products': products,
|
||||
'/masters/warehouses': warehouses,
|
||||
'/warehouses': warehouses,
|
||||
'/masters/customers': customers,
|
||||
'/customers': customers,
|
||||
'/masters/users': users,
|
||||
'/users': users,
|
||||
'/masters/groups': groups,
|
||||
'/groups': groups,
|
||||
'/masters/menus': menus,
|
||||
'/menus': menus,
|
||||
'/utilities/postal-search': postalSearch,
|
||||
'/zipcodes': postalSearch,
|
||||
'/reports': reports,
|
||||
'/reports/transactions': reportsTransactions,
|
||||
'/reports/transactions/export': reportsTransactions,
|
||||
'/reports/approvals': reportsApprovals,
|
||||
'/reports/approvals/export': reportsApprovals,
|
||||
};
|
||||
|
||||
/// 주어진 [resource] 문자열을 서버 표준 경로로 정규화한다.
|
||||
///
|
||||
/// - 앞뒤 공백 및 대소문자를 정리한다.
|
||||
/// - 맵에 등록된 라우트/별칭을 모두 표준 경로로 통일한다.
|
||||
static String normalize(String resource) {
|
||||
final sanitized = _sanitize(resource);
|
||||
if (sanitized.isEmpty) {
|
||||
return sanitized;
|
||||
}
|
||||
return _aliases[sanitized] ?? sanitized;
|
||||
}
|
||||
|
||||
static String _sanitize(String resource) {
|
||||
final trimmed = resource.trim();
|
||||
if (trimmed.isEmpty) {
|
||||
return '';
|
||||
}
|
||||
var lowered = trimmed.toLowerCase();
|
||||
|
||||
// 절대 URL이 들어오면 path 부분만 추출한다.
|
||||
final uri = Uri.tryParse(lowered);
|
||||
if (uri != null && uri.hasScheme) {
|
||||
lowered = uri.path;
|
||||
}
|
||||
|
||||
// 쿼리스트링이나 프래그먼트를 제거해 순수 경로만 남긴다.
|
||||
final queryIndex = lowered.indexOf('?');
|
||||
if (queryIndex != -1) {
|
||||
lowered = lowered.substring(0, queryIndex);
|
||||
}
|
||||
final hashIndex = lowered.indexOf('#');
|
||||
if (hashIndex != -1) {
|
||||
lowered = lowered.substring(0, hashIndex);
|
||||
}
|
||||
|
||||
if (!lowered.startsWith('/')) {
|
||||
lowered = '/$lowered';
|
||||
}
|
||||
|
||||
while (lowered.contains('//')) {
|
||||
lowered = lowered.replaceAll('//', '/');
|
||||
}
|
||||
|
||||
if (lowered.length > 1 && lowered.endsWith('/')) {
|
||||
lowered = lowered.substring(0, lowered.length - 1);
|
||||
}
|
||||
return lowered;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user