Files
Gnuboard7/lang/en/activity_log.php
T
HeuJung d17ea28da5 fix(core,board,ecommerce,page,kginicis): 정책값 하드코딩·계약 분리 결함 일괄 수정
관리자 환경설정이 값을 저장은 하지만 실제 동작에는 닿지 않던 결함군을 정리했다.
설정 화면(min/max)·저장 검증(FormRequest)·런타임 적용(Service) 세 계층이 각자
리터럴을 들고 있어 서로 조용히 갈라지던 것이 공통 원인이다.

경계값 SSoT 도입:
- config/core.php `settings_limits` 를 단일 출처로 두고, FormRequest 는 이 값으로
 규칙을 만들고 화면은 설정 응답의 `_meta.limits` 로 같은 값을 받아 바인딩한다.
- 게시판·이커머스도 각 모듈 config 의 limits 를 동일 구조로 노출한다.

적용되지 않던 정책을 실제로 적용:
- 비밀번호 최소 길이·특수문자 필수(신규 지정 7개 경로. 로그인은 제외 — 정책을
 올렸을 때 기존 회원이 자기 계정에 접근조차 못 하는 데드락을 막기 위함)
- 계정 잠금 시간 0 = 무한대(전용 컬럼 분리. timestamp 상한과 NULL 규약 때문에
 기존 컬럼 재사용이 불가능하다) + 관리자 수동 해제 경로
- 업로드 최대 크기·허용 확장자, 게시판 첨부 개수·댓글 깊이, 페이지 첨부 정책,
 장바구니 수량·구매 한도, 마일리지 사용 한도, 주문 부가세

파생 결함:
- 큐 Job(sync 드라이버)이 진행 중인 요청의 Request 바인딩을 덮어써, 뒤이어 실행되는
 훅 리스너가 헤더를 잃고 조용히 건너뛰었다. Job 이 원 바인딩을 복원하도록 고치고,
 전송 헤더가 필요한 리스너는 동기 실행으로 선언한다.
- 확장 업데이트 실패 시 상태만 되돌리고 상태 캐시를 비우지 않아, 그 확장의 관리자
 화면만 캐시 TTL(기본 하루) 동안 404 로 남았다. 실패 경로에도 무효화를 대칭으로
 두고, 빈 목록 자체를 캐시하지 않는다.
- 글 작성 시 첨부 파일이 Service 로 전달되지 않아 검증·권한은 통과하고 첨부만 사라졌다.
- 환경설정 저장 실패 안내가 내부 설정 키를 그대로 노출했다(105개 항목에 라벨 부여).

재발 방지:
- audit 룰 3종(레이아웃 경계 리터럴 / FormRequest 경계 불일치 / Service 재클램프)
- 테스트 실행 범위 강제 훅(check-test-scope)
- 트러블슈팅 사례 2건(큐 Job 요청 오염 / 확장 상태 캐시 고착)

공개 이슈: gnuboard/g7
2026-07-30 07:52:24 +09:00

301 lines
13 KiB
PHP

<?php
return [
// Activity log messages
'fetch_success' => 'Activity log information retrieved successfully.',
'fetch_failed' => 'Failed to retrieve activity log information.',
'delete_success' => 'Activity log has been deleted.',
'bulk_delete_success' => 'Selected activity logs have been deleted.',
'delete_failed' => 'Failed to delete activity log.',
// Validation messages
'validation' => [
'ids_required' => 'Please select activity logs to delete.',
'ids_min' => 'Please select at least one activity log to delete.',
'id_not_found' => 'The selected activity log was not found.',
'log_type_invalid' => 'The selected log type is invalid.',
'date_range_invalid' => 'The end date must be the same as or after the start date.',
'per_page_min' => 'Items per page must be at least 1.',
'per_page_max' => 'Items per page must not exceed 100.',
],
// Log type labels
'type' => [
'admin' => 'Admin',
'user' => 'User',
'system' => 'System',
],
// Action labels (last segment based)
'action' => [
'created' => 'Created',
'create' => 'Created',
'updated' => 'Updated',
'update' => 'Updated',
'deleted' => 'Deleted',
'delete' => 'Deleted',
'login' => 'Login',
'logout' => 'Logout',
'login_failed' => 'Login failed',
'account_locked' => 'Account locked',
'account_unlocked' => 'Account unlocked',
'request' => 'Request',
'expired' => 'Expired',
'verify' => 'Identity verified',
'verify_failed' => 'Identity verification failed',
'export' => 'Export',
'import' => 'Import',
'index' => 'List Viewed',
'show' => 'Details Viewed',
'search' => 'Search',
'install' => 'Installed',
'activate' => 'Activated',
'deactivate' => 'Deactivated',
'uninstall' => 'Uninstalled',
'save' => 'Saved',
'run' => 'Executed',
'duplicate' => 'Duplicated',
'upload' => 'Uploaded',
'toggle_status' => 'Status Toggled',
'bulk_update' => 'Bulk Updated',
'bulk_delete' => 'Bulk Deleted',
'bulk_update_status' => 'Bulk Status Changed',
'refund' => 'Refunded',
'publish' => 'Published',
'register' => 'Registered',
'reset_password' => 'Password Reset',
'forgot_password' => 'Password Recovery',
'record_consents' => 'Consent Recorded',
'check' => 'Checked',
'sync_permissions' => 'Permissions Synchronized',
'sync_roles' => 'Roles Synchronized',
'reply' => 'Replied',
'toggle' => 'Toggled',
// Additional actions
'withdraw' => 'Withdrawn',
'update_order' => 'Order Changed',
'refresh_layouts' => 'Layouts Refreshed',
'version_update' => 'Version Updated',
'version_restore' => 'Version Restored',
'reset' => 'Reset',
// Ecommerce/Board common
],
// Description templates (used as description_key)
'description' => [
// User management
'user_index' => 'User list viewed',
'user_create' => 'User created (ID: :user_id)',
'user_show' => 'User details viewed (ID: :user_id)',
'user_update' => 'User updated (ID: :user_id)',
'user_delete' => 'User deleted (ID: :user_id)',
'user_withdraw' => 'User withdrawn (ID: :user_id)',
'user_statistics' => 'User statistics viewed',
'user_recent' => 'Recent users viewed',
'user_search' => 'User search performed',
'user_check_email' => 'Email duplication checked',
'user_update_language' => 'User language setting changed',
'user_bulk_update_status' => 'Users status bulk updated (:count items)',
// Role management
'role_index' => 'Role list viewed',
'role_active' => 'Active role list viewed',
'role_show' => 'Role details viewed (ID: :role_id)',
'role_create' => 'Role created (ID: :role_id)',
'role_update' => 'Role updated (ID: :role_id)',
'role_delete' => 'Role deleted (ID: :role_id)',
'role_toggle_status' => 'Role status toggled (ID: :role_id)',
'role_sync_permissions' => 'Role permissions synchronized (ID: :role_id)',
// Permission management
'permission_index' => 'Permission list viewed',
// Menu management
'menu_index' => 'Menu list viewed',
'menu_hierarchy' => 'Menu hierarchy viewed',
'menu_active' => 'Active menu list viewed',
'menu_show' => 'Menu details viewed (ID: :menu_id)',
'menu_create' => 'Menu created (ID: :menu_id)',
'menu_update' => 'Menu updated (ID: :menu_id)',
'menu_delete' => 'Menu deleted (ID: :menu_id)',
'menu_update_order' => 'Menu order changed',
'menu_toggle_status' => 'Menu status toggled (ID: :menu_id)',
'menu_sync_roles' => 'Menu roles synchronized (ID: :menu_id)',
'menu_get_by_extension' => 'Menus by extension viewed (:extension_type: :extension_identifier)',
// Settings management
'settings_index' => 'Settings list viewed',
'settings_save' => 'Settings saved',
'settings_show' => 'Setting viewed',
'settings_update' => 'Setting updated',
'settings_system_info' => 'System information viewed',
'settings_clear_cache' => 'Cache cleared',
'settings_optimize_system' => 'System optimized',
'settings_backup_database' => 'Database backed up',
'settings_get_app_key' => 'App key viewed',
'settings_app_key_regenerated' => 'App key regenerated',
'settings_backup' => 'Backup created',
'settings_restore' => 'Backup restored',
'settings_test_mail' => 'Mail sending tested',
'settings_test_driver_connection' => 'Driver connection tested',
// Authentication
'auth_login' => 'Admin login',
'auth_logout' => 'Admin logout',
'auth_register' => 'User registered',
'auth_forgot_password' => 'Password reset requested',
'auth_reset_password' => 'Password reset',
'auth_record_consents' => 'Consent recorded',
'auth_login_failed' => 'Login failed (:email)',
'auth_account_locked' => 'Account locked (:attempts attempts, :minutes min lockout)',
'auth_account_locked_permanently' => 'Account locked permanently (:attempts attempts, administrator unlock required)',
'auth_account_unlocked' => 'Account unlocked (:email)',
// Schedule management
'schedule_index' => 'Schedule list viewed',
'schedule_show' => 'Schedule details viewed (ID: :schedule_id)',
'schedule_create' => 'Schedule created (ID: :schedule_id)',
'schedule_update' => 'Schedule updated (ID: :schedule_id)',
'schedule_delete' => 'Schedule deleted (ID: :schedule_id)',
'schedule_run' => 'Schedule manually executed (ID: :schedule_id)',
'schedule_duplicate' => 'Schedule duplicated',
'schedule_bulk_update_status' => 'Schedule status bulk updated (:count items)',
'schedule_bulk_delete' => 'Schedules bulk deleted (:count items)',
'schedule_statistics' => 'Schedule statistics viewed',
'schedule_history' => 'Schedule execution history viewed (ID: :schedule_id)',
'schedule_delete_history' => 'Schedule history deleted',
// Dashboard
'dashboard_stats' => 'Dashboard statistics viewed',
'dashboard_resources' => 'Dashboard resources viewed',
'dashboard_activities' => 'Dashboard activities viewed',
'dashboard_alerts' => 'Dashboard alerts viewed',
// Attachment management
'attachment_upload' => 'File uploaded',
'attachment_upload_batch' => 'Files batch uploaded',
'attachment_delete' => 'File deleted',
'attachment_bulk_delete' => 'Files bulk deleted',
'attachment_reorder' => 'File order changed',
// Layout management
'layout_index' => 'Layout list viewed',
'layout_show' => 'Layout details viewed (:layout_path)',
'layout_update' => 'Layout updated (:layout_path)',
'layout_versions_index' => 'Layout versions viewed (:layout_path)',
'layout_version_show' => 'Layout version viewed (:layout_path)',
'layout_version_restore' => 'Layout version restored (:layout_path)',
// Mail template management
'mail_template_update' => 'Mail template updated (:template_name)',
'mail_template_toggle_active' => 'Mail template status toggled (:template_name)',
// Module management
'module_index' => 'Module list viewed',
'module_installed' => 'Installed module list viewed',
'module_uninstalled' => 'Uninstalled module list viewed',
'module_show' => 'Module details viewed (:module_name)',
'module_install' => 'Module installed (:module_name)',
'module_activate' => 'Module activated (:module_name)',
'module_deactivate' => 'Module deactivated (:module_name)',
'module_uninstall' => 'Module uninstalled (:module_name)',
'module_uninstall_info' => 'Module uninstall info viewed (Module: :module_name)',
'module_check_updates' => 'Module updates checked',
'module_update' => 'Module updated (:module_name)',
'module_refresh_layouts' => 'Module layouts refreshed (:module_name)',
'module_dependent_templates' => 'Module dependent templates viewed',
'module_install_from_file' => 'Module installed from file',
'module_install_from_github' => 'Module installed from GitHub',
// Module settings
'module_settings_save' => 'Module settings saved (:module_name)',
'module_settings_reset' => 'Module settings reset (:module_name)',
// Plugin management
'plugin_index' => 'Plugin list viewed',
'plugin_installed' => 'Installed plugin list viewed',
'plugin_show' => 'Plugin details viewed (:plugin_name)',
'plugin_install' => 'Plugin installed (:plugin_name)',
'plugin_activate' => 'Plugin activated (:plugin_name)',
'plugin_deactivate' => 'Plugin deactivated (:plugin_name)',
'plugin_uninstall' => 'Plugin uninstalled (:plugin_name)',
'plugin_uninstall_info' => 'Plugin uninstall info viewed (Plugin: :plugin_name)',
'plugin_check_updates' => 'Plugin updates checked',
'plugin_update' => 'Plugin updated (:plugin_name)',
'plugin_refresh_layouts' => 'Plugin layouts refreshed (:plugin_name)',
'plugin_dependent_templates' => 'Plugin dependent templates viewed',
// Plugin settings
'plugin_settings_save' => 'Plugin settings saved (:plugin_name)',
'plugin_settings_reset' => 'Plugin settings reset (:plugin_name)',
// Template management
'template_index' => 'Template list viewed',
'template_show' => 'Template details viewed (:template_name)',
'template_install' => 'Template installed (:template_name)',
'template_activate' => 'Template activated (:template_name)',
'template_deactivate' => 'Template deactivated (:template_name)',
'template_uninstall' => 'Template uninstalled (:template_name)',
'template_check_updates' => 'Template updates checked',
'template_check_modified_layouts' => 'Template modified layouts checked (:template_name)',
'template_update' => 'Template updated (:template_name)',
'template_version_update' => 'Template version updated (:template_name)',
'template_install_from_file' => 'Template installed from file',
'template_install_from_github' => 'Template installed from GitHub',
'template_refresh_layouts' => 'Template layouts refreshed (:template_name)',
// Core update
'core_update_check' => 'Core update checked',
'core_update_update' => 'Core update executed',
// Activity log
'activity_log_index' => 'Activity log list viewed',
'activity_log_delete' => 'Activity log deleted (ID: :log_id)',
'activity_log_bulk_delete' => 'Activity logs bulk deleted (:count entries)',
],
// ChangeDetector field labels
'fields' => [
// User
'name' => 'Name',
'nickname' => 'Nickname',
'email' => 'Email',
'language' => 'Language',
'timezone' => 'Timezone',
'country' => 'Country',
'status' => 'Status',
'is_super' => 'Super Admin',
'homepage' => 'Homepage',
'mobile' => 'Mobile',
'phone' => 'Phone',
'zipcode' => 'Zip Code',
'address' => 'Address',
'address_detail' => 'Address Detail',
'bio' => 'Bio',
'admin_memo' => 'Admin Memo',
// Role
'identifier' => 'Identifier',
'is_active' => 'Active',
// Menu
'url' => 'URL',
'icon' => 'Icon',
'parent_id' => 'Parent',
'order' => 'Order',
// Schedule
'command' => 'Command',
'expression' => 'Expression',
'without_overlapping' => 'Without Overlapping',
'run_in_maintenance' => 'Run in Maintenance',
'timeout' => 'Timeout',
// MailTemplate
'subject' => 'Subject',
'body' => 'Body',
'is_default' => 'Default',
],
];