Changeset 3441244
- Timestamp:
- 01/16/2026 08:03:48 PM (2 months ago)
- Location:
- nhrrob-secure
- Files:
-
- 14 added
- 24 edited
- 1 copied
-
tags/1.2.0 (copied) (copied from nhrrob-secure/trunk)
-
tags/1.2.0/assets/src/components/AuditLog.js (added)
-
tags/1.2.0/assets/src/components/Hardening.js (added)
-
tags/1.2.0/assets/src/components/SessionManager.js (added)
-
tags/1.2.0/assets/src/components/VulnerabilityChecker.js (modified) (1 diff)
-
tags/1.2.0/assets/src/index.js (modified) (3 diffs)
-
tags/1.2.0/assets/src/style.css (modified) (2 diffs)
-
tags/1.2.0/build/admin.asset.php (modified) (1 diff)
-
tags/1.2.0/build/admin.css (modified) (12 diffs)
-
tags/1.2.0/build/admin.js (modified) (1 diff)
-
tags/1.2.0/build/profile.asset.php (modified) (1 diff)
-
tags/1.2.0/build/profile.css (modified) (6 diffs)
-
tags/1.2.0/includes/Admin/Api.php (modified) (6 diffs)
-
tags/1.2.0/includes/App.php (modified) (2 diffs)
-
tags/1.2.0/includes/AuditLog.php (added)
-
tags/1.2.0/includes/Hardening.php (added)
-
tags/1.2.0/includes/SessionManager.php (added)
-
tags/1.2.0/nhrrob-secure.php (modified) (5 diffs)
-
tags/1.2.0/readme.txt (modified) (4 diffs)
-
tags/1.2.0/uninstall.php (added)
-
trunk/assets/src/components/AuditLog.js (added)
-
trunk/assets/src/components/Hardening.js (added)
-
trunk/assets/src/components/SessionManager.js (added)
-
trunk/assets/src/components/VulnerabilityChecker.js (modified) (1 diff)
-
trunk/assets/src/index.js (modified) (3 diffs)
-
trunk/assets/src/style.css (modified) (2 diffs)
-
trunk/build/admin.asset.php (modified) (1 diff)
-
trunk/build/admin.css (modified) (12 diffs)
-
trunk/build/admin.js (modified) (1 diff)
-
trunk/build/profile.asset.php (modified) (1 diff)
-
trunk/build/profile.css (modified) (6 diffs)
-
trunk/includes/Admin/Api.php (modified) (6 diffs)
-
trunk/includes/App.php (modified) (2 diffs)
-
trunk/includes/AuditLog.php (added)
-
trunk/includes/Hardening.php (added)
-
trunk/includes/SessionManager.php (added)
-
trunk/nhrrob-secure.php (modified) (5 diffs)
-
trunk/readme.txt (modified) (4 diffs)
-
trunk/uninstall.php (added)
Legend:
- Unmodified
- Added
- Removed
-
nhrrob-secure/tags/1.2.0/assets/src/components/VulnerabilityChecker.js
r3438122 r3441244 115 115 <a href="plugins.php" style={{ textDecoration: 'none', color: 'inherit' }}> 116 116 {decodeEntities(plugin.name)} 117 </a> 117 </a> 118 118 <span style={{ fontWeight: 'normal', color: '#666' }}> ({plugin.version})</span> 119 119 </strong> -
nhrrob-secure/tags/1.2.0/assets/src/index.js
r3438122 r3441244 13 13 import VulnerabilityChecker from './components/VulnerabilityChecker'; 14 14 import FileScanner from './components/FileScanner'; 15 import Hardening from './components/Hardening'; 16 import SessionManager from './components/SessionManager'; 17 import AuditLog from './components/AuditLog'; 15 18 import './style.css'; 16 19 … … 124 127 <CustomLoginPage settings={settings} updateSetting={updateSetting} /> 125 128 <TwoFactorAuth settings={settings} updateSetting={updateSetting} /> 129 <Hardening settings={settings} updateSetting={updateSetting} /> 126 130 <FileProtection settings={settings} updateSetting={updateSetting} /> 127 131 <VulnerabilityChecker /> 128 132 <FileScanner /> 133 <SessionManager settings={settings} updateSetting={updateSetting} /> 134 <AuditLog settings={settings} updateSetting={updateSetting} /> 129 135 </div> 130 136 … … 148 154 render(<SettingsApp />, rootElement); 149 155 } 150 -
nhrrob-secure/tags/1.2.0/assets/src/style.css
r3438122 r3441244 134 134 } 135 135 136 .dark-mode .components-text-control__input { 136 .dark-mode .components-text-control__input, 137 .dark-mode .components-textarea-control__input { 137 138 background-color: #2c3338 !important; 138 139 border-color: #43494e !important; 139 140 color: #f0f0f1 !important; 141 } 142 143 .dark-mode .components-placeholder__input::placeholder, 144 .dark-mode input::placeholder, 145 .dark-mode textarea::placeholder { 146 color: rgba(240, 240, 241, 0.6) !important; 147 } 148 149 /* Session Manager Dark Mode */ 150 .dark-mode .session-item.bg-gray-50 { 151 background-color: rgba(255, 255, 255, 0.03) !important; 152 border-color: var(--nhrrob-secure-border) !important; 153 } 154 155 .dark-mode .session-item.bg-blue-50 { 156 background-color: rgba(34, 113, 177, 0.15) !important; 157 border-color: var(--nhrrob-secure-border) !important; 158 } 159 160 .dark-mode .session-item .text-gray-700 { 161 color: var(--nhrrob-secure-text) !important; 162 } 163 164 .dark-mode .session-item .text-gray-500 { 165 color: var(--nhrrob-secure-text-muted) !important; 166 } 167 168 .dark-mode .session-item .bg-blue-100 { 169 background-color: rgba(34, 113, 177, 0.3) !important; 170 color: #72aee6 !important; 171 } 172 173 /* Hardening Headers */ 174 .nhrrob-secure-setting-subtitle { 175 @apply text-sm font-semibold mb-3 mt-0 uppercase tracking-wide opacity-80; 176 color: var(--nhrrob-secure-text-muted); 177 } 178 179 .dark-mode .nhrrob-secure-setting-subtitle { 180 color: #a7aaad; 140 181 } 141 182 … … 358 399 } 359 400 } 401 402 /* Retention Select */ 403 .nhrrob-secure-retention-select select { 404 @apply h-8 py-0 pr-8 pl-2 text-xs border-gray-300; 405 border-color: var(--nhrrob-secure-border); 406 color: var(--nhrrob-secure-text); 407 background-color: var(--nhrrob-secure-bg); 408 } 409 410 .nhrrob-secure-settings.dark-mode .nhrrob-secure-retention-select select { 411 background-color: #2c3338 !important; 412 /* Darker input bg */ 413 border-color: var(--nhrrob-secure-border) !important; 414 color: var(--nhrrob-secure-text) !important; 415 } 416 417 .nhrrob-secure-retention-select .components-base-control__field { 418 @apply mb-0; 419 } 420 421 422 423 /* Audit Log Table */ 424 .nhrrob-secure-audit-table-wrapper { 425 @apply overflow-x-auto border rounded mt-5; 426 border-color: var(--nhrrob-secure-border); 427 } 428 429 .nhrrob-secure-audit-table { 430 @apply w-full border-collapse text-[13px]; 431 background: var(--nhrrob-secure-card-bg); 432 color: var(--nhrrob-secure-text-muted); 433 } 434 435 .nhrrob-secure-audit-table th, 436 .nhrrob-secure-audit-table td { 437 @apply p-3 text-left border-b; 438 border-color: var(--nhrrob-secure-border); 439 } 440 441 .nhrrob-secure-audit-table th { 442 @apply font-semibold; 443 background-color: var(--nhrrob-secure-bg); 444 color: var(--nhrrob-secure-text); 445 } 446 447 .nhrrob-secure-audit-table tr:last-child td { 448 @apply border-b-0; 449 } 450 451 .nhrrob-secure-audit-table tr:hover td { 452 background-color: var(--nhrrob-secure-bg); 453 } 454 455 .nhrrob-secure-badge { 456 @apply px-1.5 py-0.5 rounded text-[11px] uppercase font-medium; 457 background-color: var(--nhrrob-secure-bg); 458 color: var(--nhrrob-secure-text); 459 } 460 461 /* Dark Mode support for table */ 462 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table-wrapper { 463 border-color: #3c434a; 464 } 465 466 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table { 467 background: #1e1e1e; 468 color: #dcdcde; 469 } 470 471 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table th { 472 background: #2c2c2c; 473 color: #ffffff; 474 border-bottom-color: #3c434a; 475 } 476 477 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table td { 478 border-bottom-color: #3c434a; 479 } 480 481 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table tr:hover td { 482 background: #2c2c2c; 483 } 484 485 .nhrrob-secure-settings.dark-mode .nhrrob-secure-badge { 486 background: #3c434a; 487 color: #dcdcde; 488 } 489 490 .nhrrob-secure-pagination { 491 @apply flex justify-center items-center gap-4 mt-5; 492 } 493 494 .nhrrob-secure-page-info { 495 @apply text-[13px]; 496 color: var(--nhrrob-secure-text-muted); 497 } 498 499 .nhrrob-secure-settings.dark-mode .nhrrob-secure-page-info { 500 color: #a7aaad; 501 } 502 503 .no-logs { 504 @apply text-center p-8 !important; 505 color: var(--nhrrob-secure-text-muted); 506 } 507 508 /* Severity indicators */ 509 .severity-2 td:first-child { 510 @apply border-l-4 border-l-yellow-400; 511 } 512 513 .severity-3 td:first-child { 514 @apply border-l-4 border-l-red-600; 515 } -
nhrrob-secure/tags/1.2.0/build/admin.asset.php
r3438122 r3441244 1 <?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-components', 'wp-element', 'wp-html-entities', 'wp-i18n'), 'version' => ' e9b337e5f5ffe2cea663');1 <?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-components', 'wp-element', 'wp-html-entities', 'wp-i18n'), 'version' => '876f03e1a6accd816f8d'); -
nhrrob-secure/tags/1.2.0/build/admin.css
r3438122 r3441244 161 161 justify-content: space-between; 162 162 gap: 1rem; 163 } 164 165 .nhrrob-secure-card-header-actions { 166 display: flex; 167 align-items: center; 168 gap: 0.75rem; 163 169 } 164 170 … … 181 187 } 182 188 183 .dark-mode .components-text-control__input { 189 .dark-mode .components-text-control__input, 190 .dark-mode .components-textarea-control__input { 184 191 background-color: #2c3338 !important; 185 192 border-color: #43494e !important; 186 193 color: #f0f0f1 !important; 194 } 195 196 .dark-mode .components-placeholder__input::-moz-placeholder, .dark-mode input::-moz-placeholder, .dark-mode textarea::-moz-placeholder { 197 color: rgba(240, 240, 241, 0.6) !important; 198 } 199 200 .dark-mode .components-placeholder__input::placeholder, 201 .dark-mode input::placeholder, 202 .dark-mode textarea::placeholder { 203 color: rgba(240, 240, 241, 0.6) !important; 204 } 205 206 /* Session Manager Dark Mode */ 207 .dark-mode .session-item.bg-gray-50 { 208 background-color: rgba(255, 255, 255, 0.03) !important; 209 border-color: var(--nhrrob-secure-border) !important; 210 } 211 212 .dark-mode .session-item.bg-blue-50 { 213 background-color: rgba(34, 113, 177, 0.15) !important; 214 border-color: var(--nhrrob-secure-border) !important; 215 } 216 217 .dark-mode .session-item .text-gray-700 { 218 color: var(--nhrrob-secure-text) !important; 219 } 220 221 .dark-mode .session-item .text-gray-500 { 222 color: var(--nhrrob-secure-text-muted) !important; 223 } 224 225 .dark-mode .session-item .bg-blue-100 { 226 background-color: rgba(34, 113, 177, 0.3) !important; 227 color: #72aee6 !important; 228 } 229 230 /* Hardening Headers */ 231 .nhrrob-secure-setting-subtitle { 232 margin-bottom: 0.75rem; 233 margin-top: 0px; 234 font-size: 0.875rem; 235 line-height: 1.25rem; 236 font-weight: 600; 237 text-transform: uppercase; 238 letter-spacing: 0.025em; 239 opacity: 0.8; 240 color: var(--nhrrob-secure-text-muted); 241 } 242 243 .dark-mode .nhrrob-secure-setting-subtitle { 244 color: #a7aaad; 187 245 } 188 246 … … 394 452 } 395 453 454 .dark-mode .session-item .nhrrob-secure-card-subtitle { 455 color: var(--nhrrob-secure-text-muted); 456 } 457 396 458 .nhrrob-secure-card-subtitle { 397 459 margin: 0px; … … 424 486 background-color: transparent; 425 487 } 488 489 .dark-mode .session-item.nhrrob-result-group-title { 490 background-color: rgba(255, 255, 255, 0.03); 491 border-color: var(--nhrrob-secure-border); 492 } 426 493 427 494 .nhrrob-result-group-title { … … 471 538 } 472 539 540 .dark-mode .nhrrob-result-row:hover.session-item { 541 background-color: rgba(255, 255, 255, 0.03); 542 border-color: var(--nhrrob-secure-border); 543 } 544 473 545 .nhrrob-result-row:hover { 474 546 --tw-bg-opacity: 1; … … 501 573 color: rgb(229 231 235 / var(--tw-text-opacity, 1)); 502 574 } 575 576 .dark-mode .session-item .nhrrob-file-meta { 577 color: var(--nhrrob-secure-text-muted); 578 } 503 579 504 580 .nhrrob-file-meta { … … 538 614 margin-bottom: 1rem; 539 615 } 616 .ml-2 { 617 margin-left: 0.5rem; 618 } 540 619 .ml-5 { 541 620 margin-left: 1.25rem; … … 544 623 margin-top: 0px; 545 624 } 625 .mt-1 { 626 margin-top: 0.25rem; 627 } 546 628 .mt-4 { 547 629 margin-top: 1rem; 548 630 } 631 .block { 632 display: block; 633 } 634 .flex { 635 display: flex; 636 } 549 637 .table { 550 638 display: table; … … 556 644 display: none; 557 645 } 646 .w-64 { 647 width: 16rem; 648 } 649 .w-full { 650 width: 100%; 651 } 558 652 .grid-cols-2 { 559 653 grid-template-columns: repeat(2, minmax(0, 1fr)); 560 654 } 655 .items-start { 656 align-items: flex-start; 657 } 658 .justify-center { 659 justify-content: center; 660 } 661 .justify-between { 662 justify-content: space-between; 663 } 561 664 .gap-2 { 562 665 gap: 0.5rem; 563 666 } 667 .truncate { 668 overflow: hidden; 669 text-overflow: ellipsis; 670 white-space: nowrap; 671 } 672 .rounded { 673 border-radius: 0.25rem; 674 } 675 .rounded-full { 676 border-radius: 9999px; 677 } 678 .border { 679 border-width: 1px; 680 } 564 681 .border-t { 565 682 border-top-width: 1px; 683 } 684 .border-blue-200 { 685 --tw-border-opacity: 1; 686 border-color: rgb(191 219 254 / var(--tw-border-opacity, 1)); 566 687 } 567 688 .border-gray-100 { … … 569 690 border-color: rgb(243 244 246 / var(--tw-border-opacity, 1)); 570 691 } 692 .border-gray-200 { 693 --tw-border-opacity: 1; 694 border-color: rgb(229 231 235 / var(--tw-border-opacity, 1)); 695 } 696 .bg-blue-100 { 697 --tw-bg-opacity: 1; 698 background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1)); 699 } 700 .bg-blue-50 { 701 --tw-bg-opacity: 1; 702 background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1)); 703 } 704 .bg-gray-50 { 705 --tw-bg-opacity: 1; 706 background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1)); 707 } 708 .p-3 { 709 padding: 0.75rem; 710 } 711 .px-2 { 712 padding-left: 0.5rem; 713 padding-right: 0.5rem; 714 } 715 .py-0\.5 { 716 padding-top: 0.125rem; 717 padding-bottom: 0.125rem; 718 } 719 .pt-3 { 720 padding-top: 0.75rem; 721 } 571 722 .pt-4 { 572 723 padding-top: 1rem; 724 } 725 .font-mono { 726 font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 573 727 } 574 728 .text-sm { … … 580 734 line-height: 1rem; 581 735 } 736 .font-medium { 737 font-weight: 500; 738 } 582 739 .font-semibold { 583 740 font-weight: 600; 584 741 } 742 .text-blue-800 { 743 --tw-text-opacity: 1; 744 color: rgb(30 64 175 / var(--tw-text-opacity, 1)); 745 } 746 .text-gray-400 { 747 --tw-text-opacity: 1; 748 color: rgb(156 163 175 / var(--tw-text-opacity, 1)); 749 } 585 750 .text-gray-500 { 586 751 --tw-text-opacity: 1; 587 752 color: rgb(107 114 128 / var(--tw-text-opacity, 1)); 753 } 754 .text-gray-700 { 755 --tw-text-opacity: 1; 756 color: rgb(55 65 81 / var(--tw-text-opacity, 1)); 588 757 } 589 758 .filter { … … 608 777 } 609 778 } 779 780 /* Retention Select */ 781 .nhrrob-secure-retention-select select { 782 height: 2rem; 783 --tw-border-opacity: 1; 784 border-color: rgb(209 213 219 / var(--tw-border-opacity, 1)); 785 padding-top: 0px; 786 padding-bottom: 0px; 787 padding-right: 2rem; 788 padding-left: 0.5rem; 789 font-size: 0.75rem; 790 line-height: 1rem; 791 border-color: var(--nhrrob-secure-border); 792 color: var(--nhrrob-secure-text); 793 background-color: var(--nhrrob-secure-bg); 794 } 795 796 .nhrrob-secure-settings.dark-mode .nhrrob-secure-retention-select select { 797 background-color: #2c3338 !important; 798 /* Darker input bg */ 799 border-color: var(--nhrrob-secure-border) !important; 800 color: var(--nhrrob-secure-text) !important; 801 } 802 803 .nhrrob-secure-retention-select .components-base-control__field { 804 margin-bottom: 0px; 805 } 806 807 808 809 /* Audit Log Table */ 810 .nhrrob-secure-audit-table-wrapper { 811 margin-top: 1.25rem; 812 overflow-x: auto; 813 border-radius: 0.25rem; 814 border-width: 1px; 815 border-color: var(--nhrrob-secure-border); 816 } 817 818 .nhrrob-secure-audit-table { 819 width: 100%; 820 border-collapse: collapse; 821 font-size: 13px; 822 background: var(--nhrrob-secure-card-bg); 823 color: var(--nhrrob-secure-text-muted); 824 } 825 826 .nhrrob-secure-audit-table th, 827 .nhrrob-secure-audit-table td { 828 border-bottom-width: 1px; 829 padding: 0.75rem; 830 text-align: left; 831 border-color: var(--nhrrob-secure-border); 832 } 833 834 .nhrrob-secure-audit-table th { 835 font-weight: 600; 836 background-color: var(--nhrrob-secure-bg); 837 color: var(--nhrrob-secure-text); 838 } 839 840 .nhrrob-secure-audit-table tr:last-child td { 841 border-bottom-width: 0px; 842 } 843 844 .nhrrob-secure-audit-table tr:hover td { 845 background-color: var(--nhrrob-secure-bg); 846 } 847 848 .nhrrob-secure-badge { 849 border-radius: 0.25rem; 850 padding-left: 0.375rem; 851 padding-right: 0.375rem; 852 padding-top: 0.125rem; 853 padding-bottom: 0.125rem; 854 font-size: 11px; 855 font-weight: 500; 856 text-transform: uppercase; 857 background-color: var(--nhrrob-secure-bg); 858 color: var(--nhrrob-secure-text); 859 } 860 861 /* Dark Mode support for table */ 862 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table-wrapper { 863 border-color: #3c434a; 864 } 865 866 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table { 867 background: #1e1e1e; 868 color: #dcdcde; 869 } 870 871 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table th { 872 background: #2c2c2c; 873 color: #ffffff; 874 border-bottom-color: #3c434a; 875 } 876 877 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table td { 878 border-bottom-color: #3c434a; 879 } 880 881 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table tr:hover td { 882 background: #2c2c2c; 883 } 884 885 .nhrrob-secure-settings.dark-mode .nhrrob-secure-badge { 886 background: #3c434a; 887 color: #dcdcde; 888 } 889 890 .nhrrob-secure-pagination { 891 margin-top: 1.25rem; 892 display: flex; 893 align-items: center; 894 justify-content: center; 895 gap: 1rem; 896 } 897 898 .nhrrob-secure-page-info { 899 font-size: 13px; 900 color: var(--nhrrob-secure-text-muted); 901 } 902 903 .nhrrob-secure-settings.dark-mode .nhrrob-secure-page-info { 904 color: #a7aaad; 905 } 906 907 .no-logs { 908 padding: 2rem !important; 909 text-align: center !important; 910 color: var(--nhrrob-secure-text-muted); 911 } 912 913 /* Severity indicators */ 914 .severity-2 td:first-child { 915 border-left-width: 4px; 916 --tw-border-opacity: 1; 917 border-left-color: rgb(250 204 21 / var(--tw-border-opacity, 1)); 918 } 919 920 .severity-3 td:first-child { 921 border-left-width: 4px; 922 --tw-border-opacity: 1; 923 border-left-color: rgb(220 38 38 / var(--tw-border-opacity, 1)); 924 } -
nhrrob-secure/tags/1.2.0/build/admin.js
r3438122 r3441244 1 (()=>{"use strict";var e,r={ 967(e,r,t){const n=window.React,a=window.wp.element,s=window.wp.components,l=window.wp.i18n,c=window.wp.apiFetch;var o=t.n(c);const i=({settings:e,updateSetting:r})=>(0,n.createElement)(s.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Login Protection","nhrrob-secure")),(0,n.createElement)(s.ToggleControl,{label:(0,l.__)("Enable Login Attempts Limit","nhrrob-secure"),help:(0,l.__)("Limit failed login attempts to prevent brute force attacks","nhrrob-secure"),checked:e.nhrrob_secure_limit_login_attempts,onChange:e=>r("nhrrob_secure_limit_login_attempts",e)}),e.nhrrob_secure_limit_login_attempts&&(0,n.createElement)(s.TextControl,{label:(0,l.__)("Maximum Login Attempts","nhrrob-secure"),help:(0,l.__)("Number of failed attempts before blocking (default: 5)","nhrrob-secure"),type:"number",value:e.nhrrob_secure_login_attempts_limit,onChange:e=>r("nhrrob_secure_login_attempts_limit",parseInt(e)||5),min:"1",max:"20"}),(0,n.createElement)(s.ToggleControl,{label:(0,l.__)("Enable Proxy IP Detection","nhrrob-secure"),help:(0,l.__)("Detect real IP behind proxies (Cloudflare, etc.)","nhrrob-secure"),checked:e.nhrrob_secure_enable_proxy_ip,onChange:e=>r("nhrrob_secure_enable_proxy_ip",e)}))),u=({settings:e,updateSetting:r})=>(0,n.createElement)(s.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Custom Login Page","nhrrob-secure")),(0,n.createElement)(s.ToggleControl,{label:(0,l.__)("Enable Custom Login URL","nhrrob-secure"),help:(0,l.__)("Hide wp-login.php and use a custom login URL","nhrrob-secure"),checked:e.nhrrob_secure_custom_login_page,onChange:e=>r("nhrrob_secure_custom_login_page",e)}),e.nhrrob_secure_custom_login_page&&(0,n.createElement)(s.TextControl,{label:(0,l.__)("Custom Login URL","nhrrob-secure"),help:(0,l.__)("Your login page will be accessible at this URL","nhrrob-secure"),value:e.nhrrob_secure_custom_login_url,onChange:e=>r("nhrrob_secure_custom_login_url",e),placeholder:"/hidden-access-52w"}),e.nhrrob_secure_custom_login_page&&(0,n.createElement)("div",{className:"nhrrob-secure-info"},(0,n.createElement)("strong",null,(0,l.__)("Your login URL:","nhrrob-secure")),(0,n.createElement)("code",null,window.location.origin,e.nhrrob_secure_custom_login_url)))),m=({settings:e,updateSetting:r})=>{const t=e.nhrrob_secure_2fa_enforced_roles||[],a=e.available_roles||[];return(0,n.createElement)(s.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Two-Factor Authentication","nhrrob-secure")),(0,n.createElement)(s.ToggleControl,{label:(0,l.__)("Enable Global 2FA","nhrrob-secure"),help:(0,n.createElement)(n.Fragment,null,(0,l.__)("Enables Google Authenticator support for all users. Users can set it up in their ","nhrrob-secure"),(0,n.createElement)("a",{href:nhrrobSecureSettings.profile_url,target:"_blank",rel:"noreferrer"},(0,l.__)("profile page","nhrrob-secure")),"."),checked:e.nhrrob_secure_enable_2fa,onChange:e=>r("nhrrob_secure_enable_2fa",e)}),e.nhrrob_secure_enable_2fa&&(0,n.createElement)(n.Fragment,null,(0,n.createElement)("div",{className:"nhrrob-secure-2fa-method pt-4 border-t border-gray-100"},(0,n.createElement)("h3",{className:"text-sm font-semibold mb-3"},(0,l.__)("2FA Method","nhrrob-secure")),(0,n.createElement)(s.RadioControl,{selected:e.nhrrob_secure_2fa_type||"app",options:[{label:(0,l.__)("Authenticator App (Recommended)","nhrrob-secure"),value:"app"},{label:(0,l.__)("Email OTP","nhrrob-secure"),value:"email"}],onChange:e=>r("nhrrob_secure_2fa_type",e)})),(0,n.createElement)("div",{className:"nhrrob-secure-enforced-roles pt-4 border-t border-gray-100"},(0,n.createElement)("h3",{className:"text-sm font-semibold mb-3"},(0,l.__)("Enforced 2FA by Role","nhrrob-secure")),(0,n.createElement)("p",{className:"text-xs text-gray-500 mb-4"},(0,l.__)("Users with the selected roles will be forced to set up 2FA before they can access the admin dashboard.","nhrrob-secure")),(0,n.createElement)("div",{className:"grid grid-cols-2 gap-2"},a.map(e=>(0,n.createElement)(s.CheckboxControl,{key:e.value,label:e.label,checked:t.includes(e.value),onChange:n=>((e,n)=>{const a=n?[...t,e]:t.filter(r=>r!==e);r("nhrrob_secure_2fa_enforced_roles",a)})(e.value,n)})))))))},h=({settings:e,updateSetting:r})=>(0,n.createElement)(s.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("File Protection","nhrrob-secure")),(0,n.createElement)(s.ToggleControl,{label:(0,l.__)("Protect Debug Log","nhrrob-secure"),help:(0,l.__)("Block direct access to wp-content/debug.log","nhrrob-secure"),checked:e.nhrrob_secure_protect_debug_log,onChange:e=>r("nhrrob_secure_protect_debug_log",e)}))),d=window.wp.htmlEntities,b=()=>{const[e,r]=(0,a.useState)(null),[t,c]=(0,a.useState)(!0),[i,u]=(0,a.useState)(!1),[m,h]=(0,a.useState)(null);(0,a.useEffect)(()=>{b()},[]);const b=async()=>{try{const e=await o()({path:"/nhrrob-secure/v1/vulnerability/status"});r(e),c(!1)}catch(e){h((0,l.__)("Failed to fetch vulnerability status","nhrrob-secure")),c(!1)}};if(t)return(0,n.createElement)(s.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)(s.Spinner,null)));const _=e&&(e.core.length>0||e.plugins.length>0||e.themes.length>0);return(0,n.createElement)(s.Card,{className:"nhrrob-secure-card nhrrob-secure-vulnerability-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Vulnerability Checker","nhrrob-secure")),(0,n.createElement)(s.Button,{variant:"primary",onClick:async()=>{u(!0),h(null);try{const e=await o()({path:"/nhrrob-secure/v1/vulnerability/scan",method:"POST"});r(e)}catch(e){h((0,l.__)("Failed to run vulnerability scan","nhrrob-secure"))}finally{u(!1)}},isBusy:i,disabled:i,icon:"update",iconPosition:"right"},i?(0,l.__)("Scanning...","nhrrob-secure"):(0,l.__)("Scan Now","nhrrob-secure"))),(0,n.createElement)("p",{className:"nhrrob-secure-last-scan"},(0,n.createElement)("strong",null,(0,l.__)("Last Scan:","nhrrob-secure"))," ",(g=e.last_scan)?new Date(1e3*g).toLocaleString():(0,l.__)("Never","nhrrob-secure")),m&&(0,n.createElement)(s.Notice,{status:"error",isDismissible:!1},m),_?(0,n.createElement)("div",{className:"nhrrob-secure-vulnerability-list"},(0,n.createElement)(s.Notice,{status:"warning",isDismissible:!1},(0,l.__)("Vulnerabilities detected! Please review and update the items below.","nhrrob-secure")),e.core.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("WordPress Core","nhrrob-secure")),(0,n.createElement)("ul",null,e.core.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name))))),e.plugins.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("Plugins","nhrrob-secure")),e.plugins.map((e,r)=>(0,n.createElement)("div",{key:r,className:"vulnerability-item"},(0,n.createElement)("strong",null,(0,n.createElement)("a",{href:"plugins.php",style:{textDecoration:"none",color:"inherit"}},(0,d.decodeEntities)(e.name)),(0,n.createElement)("span",{style:{fontWeight:"normal",color:"#666"}}," (",e.version,")")),(0,n.createElement)("ul",null,e.vulnerabilities.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name))))))),e.themes.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("Themes","nhrrob-secure")),e.themes.map((e,r)=>(0,n.createElement)("div",{key:r,className:"vulnerability-item"},(0,n.createElement)("strong",null,(0,d.decodeEntities)(e.name)," (",e.version,")"),(0,n.createElement)("ul",null,e.vulnerabilities.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name)))))))):(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No known vulnerabilities detected.","nhrrob-secure"))));var g},_=()=>{const[e,r]=(0,a.useState)(!1),[t,c]=(0,a.useState)(null),[i,u]=(0,a.useState)(null),[m,h]=(0,a.useState)("core"),d=async()=>{r(!0),u(null),c(null);try{const e="core"===m?"/nhrrob-secure/v1/scanner/core":"/nhrrob-secure/v1/scanner/malware",r=await o()({path:e,method:"POST"});c(r)}catch(e){u(e.message||(0,l.__)("An error occurred during scan.","nhrrob-secure"))}finally{r(!1)}};return(0,n.createElement)("div",{className:"nhrrob-secure-card nhrrob-secure-vulnerability-card padded-header"},(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("div",{className:"nhrrob-secure-header-content"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("File Scanner","nhrrob-secure")),(0,n.createElement)("p",{className:"nhrrob-secure-card-subtitle"},(0,l.__)("Scan your site for file modifications and potential malware.","nhrrob-secure"))),(0,n.createElement)("div",{className:"nhrrob-scan-controls"},(0,n.createElement)("div",{className:"nhrrob-scan-type-toggle"},(0,n.createElement)("button",{className:"nhrrob-scan-toggle-btn "+("core"===m?"active":""),onClick:()=>h("core"),disabled:e},(0,l.__)("Core Integrity","nhrrob-secure")),(0,n.createElement)("button",{className:"nhrrob-scan-toggle-btn "+("malware"===m?"active":""),onClick:()=>h("malware"),disabled:e},(0,l.__)("Malware Scan","nhrrob-secure"))),(0,n.createElement)(s.Button,{variant:"primary",onClick:()=>d(),isBusy:e,disabled:e,icon:"update",iconPosition:"right"},e?(0,l.__)("Scanning...","nhrrob-secure"):(0,l.__)("Start Scan","nhrrob-secure")))),(0,n.createElement)("div",{className:"nhrrob-card-body"},i&&(0,n.createElement)("div",{className:"notice notice-error inline-notice"},(0,n.createElement)("p",null,i)),t&&(0,n.createElement)("div",{className:"nhrrob-secure-vulnerability-list"},("core"===m&&(t.modified?.length>0||t.missing?.length>0)||"malware"===m&&t.suspicious?.length>0)&&(0,n.createElement)("div",{className:"notice notice-warning inline-notice nhrrob-warning-notice"},(0,n.createElement)("p",null,(0,l.__)("Issues detected! Please review and update the items below.","nhrrob-secure"))),"core"===m&&(0,n.createElement)(n.Fragment,null,t.modified&&t.modified.length>0&&(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Modified Core Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.modified.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e)),(0,n.createElement)(s.Button,{variant:"secondary",isSmall:!0,onClick:()=>(async e=>{if(confirm((0,l.__)("Are you sure you want to repair this file? It will be overwritten with the original version.","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/scanner/repair",method:"POST",data:{file:e}}),alert((0,l.__)("File repaired successfully.","nhrrob-secure")),d()}catch(e){alert(e.message||(0,l.__)("Repair failed.","nhrrob-secure"))}})(e)},(0,l.__)("Repair","nhrrob-secure")))))),t.missing&&t.missing.length>0&&(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Missing Core Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.missing.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e)))))),!t.modified?.length&&!t.missing?.length&&(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No modified core files found.","nhrrob-secure"))),"malware"===m&&(0,n.createElement)(n.Fragment,null,t.suspicious&&t.suspicious.length>0?(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Suspicious Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.suspicious.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e.file),(0,n.createElement)("span",{className:"nhrrob-file-meta"},e.reason)),(0,n.createElement)(s.Button,{variant:"link",isDestructive:!0,onClick:()=>(async e=>{if(confirm((0,l.__)("Are you sure you want to PERMANENTLY delete this file?","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/scanner/delete",method:"POST",data:{file:e}}),alert((0,l.__)("File deleted successfully.","nhrrob-secure")),d()}catch(e){alert(e.message||(0,l.__)("Delete failed.","nhrrob-secure"))}})(e.file)},(0,l.__)("Delete","nhrrob-secure")))))):(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No suspicious files found.","nhrrob-secure")),(0,n.createElement)("p",{className:"description nhrrob-scan-count"},(0,n.createElement)("small",null,(0,l.__)("Scanned files:","nhrrob-secure")," ",t.scanned_count))))))},g=document.getElementById("nhrrob-secure-settings-root");g&&(0,a.render)((0,n.createElement)(()=>{const[e,r]=(0,a.useState)(null),[t,c]=(0,a.useState)(!0),[d,g]=(0,a.useState)(!1),[p,E]=(0,a.useState)(null);(0,a.useEffect)(()=>{v()},[]);const v=async()=>{try{const e=await o()({path:"/nhrrob-secure/v1/settings"});r(e),c(!1)}catch(e){E({type:"error",message:(0,l.__)("Failed to load settings","nhrrob-secure")}),c(!1)}},f=(t,n)=>{r({...e,[t]:n})};return(0,a.useEffect)(()=>{e?.nhrrob_secure_dark_mode?document.body.classList.add("nhrrob-secure-dark-mode-active"):document.body.classList.remove("nhrrob-secure-dark-mode-active")},[e?.nhrrob_secure_dark_mode]),t?(0,n.createElement)("div",{className:"nhrrob-secure-loading"},(0,n.createElement)(s.Spinner,null)):(0,n.createElement)("div",{className:"nhrrob-secure-settings "+(e.nhrrob_secure_dark_mode?"dark-mode":"")},(0,n.createElement)("div",{className:"nhrrob-secure-header"},(0,n.createElement)("div",{className:"nhrrob-secure-header-main"},(0,n.createElement)("h1",null,(0,l.__)("NHR Secure Settings","nhrrob-secure")),(0,n.createElement)(s.Button,{className:"nhrrob-secure-dark-mode-toggle",icon:e.nhrrob_secure_dark_mode?(0,n.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",width:"20",height:"20"},(0,n.createElement)("path",{d:"M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58a.996.996 0 00-1.41 0 .996.996 0 000 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41L5.99 4.58zm12.37 12.37a.996.996 0 00-1.41 0 .996.996 0 000 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41l-1.06-1.06zm1.06-10.96a.996.996 0 00-1.41-1.41l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06zM7.05 18.36a.996.996 0 00-1.41-1.41l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06z"})):(0,n.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",width:"20",height:"20"},(0,n.createElement)("path",{d:"M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z"})),onClick:async()=>{const r=!e.nhrrob_secure_dark_mode;f("nhrrob_secure_dark_mode",r);try{await o()({path:"/nhrrob-secure/v1/settings",method:"POST",data:{...e,nhrrob_secure_dark_mode:r}})}catch(e){console.error("Failed to save dark mode preference",e)}},label:(0,l.__)("Toggle Dark Mode","nhrrob-secure")})),(0,n.createElement)("p",{className:"nhrrob-secure-subtitle"},(0,l.__)("Configure security features for your WordPress site","nhrrob-secure"))),p&&(0,n.createElement)(s.Notice,{status:p.type,isDismissible:!0,onRemove:()=>E(null)},p.message),(0,n.createElement)("div",{className:"nhrrob-secure-cards"},(0,n.createElement)(i,{settings:e,updateSetting:f}),(0,n.createElement)(u,{settings:e,updateSetting:f}),(0,n.createElement)(m,{settings:e,updateSetting:f}),(0,n.createElement)(h,{settings:e,updateSetting:f}),(0,n.createElement)(b,null),(0,n.createElement)(_,null)),(0,n.createElement)("div",{className:"nhrrob-secure-actions"},(0,n.createElement)(s.Button,{variant:"primary",onClick:async()=>{g(!0),E(null);try{await o()({path:"/nhrrob-secure/v1/settings",method:"POST",data:e}),E({type:"success",message:(0,l.__)("Settings saved successfully!","nhrrob-secure")})}catch(e){E({type:"error",message:(0,l.__)("Failed to save settings","nhrrob-secure")})}finally{g(!1)}},isBusy:d,disabled:d},d?(0,l.__)("Saving...","nhrrob-secure"):(0,l.__)("Save Settings","nhrrob-secure"))))},null),g)}},t={};function n(e){var a=t[e];if(void 0!==a)return a.exports;var s=t[e]={exports:{}};return r[e](s,s.exports,n),s.exports}n.m=r,e=[],n.O=(r,t,a,s)=>{if(!t){var l=1/0;for(u=0;u<e.length;u++){for(var[t,a,s]=e[u],c=!0,o=0;o<t.length;o++)(!1&s||l>=s)&&Object.keys(n.O).every(e=>n.O[e](t[o]))?t.splice(o--,1):(c=!1,s<l&&(l=s));if(c){e.splice(u--,1);var i=a();void 0!==i&&(r=i)}}return r}s=s||0;for(var u=e.length;u>0&&e[u-1][2]>s;u--)e[u]=e[u-1];e[u]=[t,a,s]},n.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return n.d(r,{a:r}),r},n.d=(e,r)=>{for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),(()=>{var e={884:0,15:0};n.O.j=r=>0===e[r];var r=(r,t)=>{var a,s,[l,c,o]=t,i=0;if(l.some(r=>0!==e[r])){for(a in c)n.o(c,a)&&(n.m[a]=c[a]);if(o)var u=o(n)}for(r&&r(t);i<l.length;i++)s=l[i],n.o(e,s)&&e[s]&&e[s][0](),e[s]=0;return n.O(u)},t=globalThis.webpackChunknhrrob_secure=globalThis.webpackChunknhrrob_secure||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})();var a=n.O(void 0,[15],()=>n(967));a=n.O(a)})();1 (()=>{"use strict";var e,r={195(e,r,t){const n=window.React,s=window.wp.element,a=window.wp.components,l=window.wp.i18n,c=window.wp.apiFetch;var o=t.n(c);const i=({settings:e,updateSetting:r})=>(0,n.createElement)(a.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Login Protection","nhrrob-secure")),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Enable Login Attempts Limit","nhrrob-secure"),help:(0,l.__)("Limit failed login attempts to prevent brute force attacks","nhrrob-secure"),checked:e.nhrrob_secure_limit_login_attempts,onChange:e=>r("nhrrob_secure_limit_login_attempts",e)}),e.nhrrob_secure_limit_login_attempts&&(0,n.createElement)(a.TextControl,{label:(0,l.__)("Maximum Login Attempts","nhrrob-secure"),help:(0,l.__)("Number of failed attempts before blocking (default: 5)","nhrrob-secure"),type:"number",value:e.nhrrob_secure_login_attempts_limit,onChange:e=>r("nhrrob_secure_login_attempts_limit",parseInt(e)||5),min:"1",max:"20"}),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Enable Proxy IP Detection","nhrrob-secure"),help:(0,l.__)("Detect real IP behind proxies (Cloudflare, etc.)","nhrrob-secure"),checked:e.nhrrob_secure_enable_proxy_ip,onChange:e=>r("nhrrob_secure_enable_proxy_ip",e)}))),u=({settings:e,updateSetting:r})=>(0,n.createElement)(a.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Custom Login Page","nhrrob-secure")),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Enable Custom Login URL","nhrrob-secure"),help:(0,l.__)("Hide wp-login.php and use a custom login URL","nhrrob-secure"),checked:e.nhrrob_secure_custom_login_page,onChange:e=>r("nhrrob_secure_custom_login_page",e)}),e.nhrrob_secure_custom_login_page&&(0,n.createElement)(a.TextControl,{label:(0,l.__)("Custom Login URL","nhrrob-secure"),help:(0,l.__)("Your login page will be accessible at this URL","nhrrob-secure"),value:e.nhrrob_secure_custom_login_url,onChange:e=>r("nhrrob_secure_custom_login_url",e),placeholder:"/hidden-access-52w"}),e.nhrrob_secure_custom_login_page&&(0,n.createElement)("div",{className:"nhrrob-secure-info"},(0,n.createElement)("strong",null,(0,l.__)("Your login URL:","nhrrob-secure")),(0,n.createElement)("code",null,window.location.origin,e.nhrrob_secure_custom_login_url)))),m=({settings:e,updateSetting:r})=>{const t=e.nhrrob_secure_2fa_enforced_roles||[],s=e.available_roles||[];return(0,n.createElement)(a.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Two-Factor Authentication","nhrrob-secure")),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Enable Global 2FA","nhrrob-secure"),help:(0,n.createElement)(n.Fragment,null,(0,l.__)("Enables Google Authenticator support for all users. Users can set it up in their ","nhrrob-secure"),(0,n.createElement)("a",{href:nhrrobSecureSettings.profile_url,target:"_blank",rel:"noreferrer"},(0,l.__)("profile page","nhrrob-secure")),"."),checked:e.nhrrob_secure_enable_2fa,onChange:e=>r("nhrrob_secure_enable_2fa",e)}),e.nhrrob_secure_enable_2fa&&(0,n.createElement)(n.Fragment,null,(0,n.createElement)("div",{className:"nhrrob-secure-2fa-method pt-4 border-t border-gray-100"},(0,n.createElement)("h3",{className:"text-sm font-semibold mb-3"},(0,l.__)("2FA Method","nhrrob-secure")),(0,n.createElement)(a.RadioControl,{selected:e.nhrrob_secure_2fa_type||"app",options:[{label:(0,l.__)("Authenticator App (Recommended)","nhrrob-secure"),value:"app"},{label:(0,l.__)("Email OTP","nhrrob-secure"),value:"email"}],onChange:e=>r("nhrrob_secure_2fa_type",e)})),(0,n.createElement)("div",{className:"nhrrob-secure-enforced-roles pt-4 border-t border-gray-100"},(0,n.createElement)("h3",{className:"text-sm font-semibold mb-3"},(0,l.__)("Enforced 2FA by Role","nhrrob-secure")),(0,n.createElement)("p",{className:"text-xs text-gray-500 mb-4"},(0,l.__)("Users with the selected roles will be forced to set up 2FA before they can access the admin dashboard.","nhrrob-secure")),(0,n.createElement)("div",{className:"grid grid-cols-2 gap-2"},s.map(e=>(0,n.createElement)(a.CheckboxControl,{key:e.value,label:e.label,checked:t.includes(e.value),onChange:n=>((e,n)=>{const s=n?[...t,e]:t.filter(r=>r!==e);r("nhrrob_secure_2fa_enforced_roles",s)})(e.value,n)})))))))},h=({settings:e,updateSetting:r})=>(0,n.createElement)(a.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("File Protection","nhrrob-secure")),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Protect Debug Log","nhrrob-secure"),help:(0,l.__)("Block direct access to wp-content/debug.log","nhrrob-secure"),checked:e.nhrrob_secure_protect_debug_log,onChange:e=>r("nhrrob_secure_protect_debug_log",e)}))),d=window.wp.htmlEntities,b=()=>{const[e,r]=(0,s.useState)(null),[t,c]=(0,s.useState)(!0),[i,u]=(0,s.useState)(!1),[m,h]=(0,s.useState)(null);(0,s.useEffect)(()=>{b()},[]);const b=async()=>{try{const e=await o()({path:"/nhrrob-secure/v1/vulnerability/status"});r(e),c(!1)}catch(e){h((0,l.__)("Failed to fetch vulnerability status","nhrrob-secure")),c(!1)}};if(t)return(0,n.createElement)(a.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)(a.Spinner,null)));const _=e&&(e.core.length>0||e.plugins.length>0||e.themes.length>0);return(0,n.createElement)(a.Card,{className:"nhrrob-secure-card nhrrob-secure-vulnerability-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Vulnerability Checker","nhrrob-secure")),(0,n.createElement)(a.Button,{variant:"primary",onClick:async()=>{u(!0),h(null);try{const e=await o()({path:"/nhrrob-secure/v1/vulnerability/scan",method:"POST"});r(e)}catch(e){h((0,l.__)("Failed to run vulnerability scan","nhrrob-secure"))}finally{u(!1)}},isBusy:i,disabled:i,icon:"update",iconPosition:"right"},i?(0,l.__)("Scanning...","nhrrob-secure"):(0,l.__)("Scan Now","nhrrob-secure"))),(0,n.createElement)("p",{className:"nhrrob-secure-last-scan"},(0,n.createElement)("strong",null,(0,l.__)("Last Scan:","nhrrob-secure"))," ",(g=e.last_scan)?new Date(1e3*g).toLocaleString():(0,l.__)("Never","nhrrob-secure")),m&&(0,n.createElement)(a.Notice,{status:"error",isDismissible:!1},m),_?(0,n.createElement)("div",{className:"nhrrob-secure-vulnerability-list"},(0,n.createElement)(a.Notice,{status:"warning",isDismissible:!1},(0,l.__)("Vulnerabilities detected! Please review and update the items below.","nhrrob-secure")),e.core.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("WordPress Core","nhrrob-secure")),(0,n.createElement)("ul",null,e.core.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name))))),e.plugins.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("Plugins","nhrrob-secure")),e.plugins.map((e,r)=>(0,n.createElement)("div",{key:r,className:"vulnerability-item"},(0,n.createElement)("strong",null,(0,n.createElement)("a",{href:"plugins.php",style:{textDecoration:"none",color:"inherit"}},(0,d.decodeEntities)(e.name)),(0,n.createElement)("span",{style:{fontWeight:"normal",color:"#666"}}," (",e.version,")")),(0,n.createElement)("ul",null,e.vulnerabilities.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name))))))),e.themes.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("Themes","nhrrob-secure")),e.themes.map((e,r)=>(0,n.createElement)("div",{key:r,className:"vulnerability-item"},(0,n.createElement)("strong",null,(0,d.decodeEntities)(e.name)," (",e.version,")"),(0,n.createElement)("ul",null,e.vulnerabilities.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name)))))))):(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No known vulnerabilities detected.","nhrrob-secure"))));var g},_=()=>{const[e,r]=(0,s.useState)(!1),[t,c]=(0,s.useState)(null),[i,u]=(0,s.useState)(null),[m,h]=(0,s.useState)("core"),d=async()=>{r(!0),u(null),c(null);try{const e="core"===m?"/nhrrob-secure/v1/scanner/core":"/nhrrob-secure/v1/scanner/malware",r=await o()({path:e,method:"POST"});c(r)}catch(e){u(e.message||(0,l.__)("An error occurred during scan.","nhrrob-secure"))}finally{r(!1)}};return(0,n.createElement)("div",{className:"nhrrob-secure-card nhrrob-secure-vulnerability-card padded-header"},(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("div",{className:"nhrrob-secure-header-content"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("File Scanner","nhrrob-secure")),(0,n.createElement)("p",{className:"nhrrob-secure-card-subtitle"},(0,l.__)("Scan your site for file modifications and potential malware.","nhrrob-secure"))),(0,n.createElement)("div",{className:"nhrrob-scan-controls"},(0,n.createElement)("div",{className:"nhrrob-scan-type-toggle"},(0,n.createElement)("button",{className:"nhrrob-scan-toggle-btn "+("core"===m?"active":""),onClick:()=>h("core"),disabled:e},(0,l.__)("Core Integrity","nhrrob-secure")),(0,n.createElement)("button",{className:"nhrrob-scan-toggle-btn "+("malware"===m?"active":""),onClick:()=>h("malware"),disabled:e},(0,l.__)("Malware Scan","nhrrob-secure"))),(0,n.createElement)(a.Button,{variant:"primary",onClick:()=>d(),isBusy:e,disabled:e,icon:"update",iconPosition:"right"},e?(0,l.__)("Scanning...","nhrrob-secure"):(0,l.__)("Start Scan","nhrrob-secure")))),(0,n.createElement)("div",{className:"nhrrob-card-body"},i&&(0,n.createElement)("div",{className:"notice notice-error inline-notice"},(0,n.createElement)("p",null,i)),t&&(0,n.createElement)("div",{className:"nhrrob-secure-vulnerability-list"},("core"===m&&(t.modified?.length>0||t.missing?.length>0)||"malware"===m&&t.suspicious?.length>0)&&(0,n.createElement)("div",{className:"notice notice-warning inline-notice nhrrob-warning-notice"},(0,n.createElement)("p",null,(0,l.__)("Issues detected! Please review and update the items below.","nhrrob-secure"))),"core"===m&&(0,n.createElement)(n.Fragment,null,t.modified&&t.modified.length>0&&(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Modified Core Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.modified.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e)),(0,n.createElement)(a.Button,{variant:"secondary",isSmall:!0,onClick:()=>(async e=>{if(confirm((0,l.__)("Are you sure you want to repair this file? It will be overwritten with the original version.","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/scanner/repair",method:"POST",data:{file:e}}),alert((0,l.__)("File repaired successfully.","nhrrob-secure")),d()}catch(e){alert(e.message||(0,l.__)("Repair failed.","nhrrob-secure"))}})(e)},(0,l.__)("Repair","nhrrob-secure")))))),t.missing&&t.missing.length>0&&(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Missing Core Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.missing.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e)))))),!t.modified?.length&&!t.missing?.length&&(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No modified core files found.","nhrrob-secure"))),"malware"===m&&(0,n.createElement)(n.Fragment,null,t.suspicious&&t.suspicious.length>0?(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Suspicious Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.suspicious.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e.file),(0,n.createElement)("span",{className:"nhrrob-file-meta"},e.reason)),(0,n.createElement)(a.Button,{variant:"link",isDestructive:!0,onClick:()=>(async e=>{if(confirm((0,l.__)("Are you sure you want to PERMANENTLY delete this file?","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/scanner/delete",method:"POST",data:{file:e}}),alert((0,l.__)("File deleted successfully.","nhrrob-secure")),d()}catch(e){alert(e.message||(0,l.__)("Delete failed.","nhrrob-secure"))}})(e.file)},(0,l.__)("Delete","nhrrob-secure")))))):(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No suspicious files found.","nhrrob-secure")),(0,n.createElement)("p",{className:"description nhrrob-scan-count"},(0,n.createElement)("small",null,(0,l.__)("Scanned files:","nhrrob-secure")," ",t.scanned_count))))))},g=({settings:e,updateSetting:r})=>(0,n.createElement)(a.Card,{className:"nhrrob-secure-card nhrrob-secure-hardening-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Hardening & Firewall","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-secure-setting-group"},(0,n.createElement)("h3",{className:"nhrrob-secure-setting-subtitle"},(0,l.__)("General Hardening","nhrrob-secure")),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Disable XML-RPC","nhrrob-secure"),help:(0,l.__)("Prevents external systems (like mobile apps and Jetpack) from accessing your site via XML-RPC. Recommended if not used.","nhrrob-secure"),checked:e.nhrrob_secure_disable_xmlrpc,onChange:e=>r("nhrrob_secure_disable_xmlrpc",e)}),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Disable File Editor","nhrrob-secure"),help:(0,l.__)("Disables the built-in theme and plugin file editor to prevent code execution if an admin account is compromised.","nhrrob-secure"),checked:e.nhrrob_secure_disable_file_editor,onChange:e=>r("nhrrob_secure_disable_file_editor",e)}),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Hide WP Version","nhrrob-secure"),help:(0,l.__)("Removes WordPress version from page source and RSS feeds to make reconnaissance harder for attackers.","nhrrob-secure"),checked:e.nhrrob_secure_hide_wp_version,onChange:e=>r("nhrrob_secure_hide_wp_version",e)}),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Disable REST API User Enumeration","nhrrob-secure"),help:(0,l.__)("Blocks access to /wp-json/wp/v2/users to prevent attackers from listing your users.","nhrrob-secure"),checked:e.nhrrob_secure_disable_rest_users,onChange:e=>r("nhrrob_secure_disable_rest_users",e)})),(0,n.createElement)("div",{className:"nhrrob-secure-setting-group border-t border-gray-100 pt-4 mt-4"},(0,n.createElement)("h3",{className:"nhrrob-secure-setting-subtitle"},(0,l.__)("Firewall Rules","nhrrob-secure")),(0,n.createElement)(a.TextareaControl,{label:(0,l.__)("Block User Agents","nhrrob-secure"),help:(0,l.__)('Enter one User-Agent per line to block. Case-insensitive partial match. Example: "HTTrack", "curl".',"nhrrob-secure"),value:e.nhrrob_secure_firewall_blocked_uas,onChange:e=>r("nhrrob_secure_firewall_blocked_uas",e),rows:5,placeholder:"SemrushBot\nAhrefsBot\nMJ12bot"})))),E=({settings:e,updateSetting:r})=>{const[t,c]=(0,s.useState)([]),[i,u]=(0,s.useState)(!1),[m,h]=(0,s.useState)(null);(0,s.useEffect)(()=>{d()},[]);const d=async()=>{u(!0),h(null);try{const e=await o()({path:"/nhrrob-secure/v1/sessions"});c(e)}catch(e){h(e.message||(0,l.__)("Failed to load sessions.","nhrrob-secure"))}finally{u(!1)}};return(0,n.createElement)(a.Card,{className:"nhrrob-secure-card nhrrob-secure-sessions-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("User Session Management","nhrrob-secure")),(0,n.createElement)(a.Button,{variant:"primary",onClick:d,isBusy:i,disabled:i,icon:"update"},(0,l.__)("Refresh","nhrrob-secure"))),(0,n.createElement)("div",{className:"nhrrob-secure-setting-group"},(0,n.createElement)(a.TextControl,{label:(0,l.__)("Idle Timeout (Minutes)","nhrrob-secure"),help:(0,l.__)("Automatically log out inactive users after X minutes. Set to 0 to disable.","nhrrob-secure"),type:"number",value:e?.nhrrob_secure_idle_timeout||0,onChange:e=>r("nhrrob_secure_idle_timeout",parseInt(e)||0),min:"0"})),m&&(0,n.createElement)(a.Notice,{status:"error",isDismissible:!1},m),(0,n.createElement)("div",{className:"nhrrob-secure-sessions-list mt-4"},(0,n.createElement)("h3",{className:"text-sm font-semibold mb-3"},(0,l.__)("Active Sessions","nhrrob-secure")),0!==t.length||i?(0,n.createElement)("div",{className:"sessions-grid"},t.map((e,r)=>(0,n.createElement)("div",{key:r,className:"session-item p-3 border rounded mb-2 "+(e.is_current?"bg-blue-50 border-blue-200":"bg-gray-50 border-gray-200")},(0,n.createElement)("div",{className:"flex justify-between items-start"},(0,n.createElement)("div",{className:"session-info"},(0,n.createElement)("div",{className:"font-medium text-gray-700"},e.ip,e.is_current&&(0,n.createElement)("span",{className:"ml-2 px-2 py-0.5 text-xs bg-blue-100 text-blue-800 rounded-full"},(0,l.__)("Current Session","nhrrob-secure"))),(0,n.createElement)("div",{className:"text-xs text-gray-500 mt-1"},(0,n.createElement)("div",null,(0,l.__)("Login:","nhrrob-secure")," ",new Date(1e3*e.login).toLocaleString()),(0,n.createElement)("div",null,(0,l.__)("Expires:","nhrrob-secure")," ",new Date(1e3*e.expiration).toLocaleString()),(0,n.createElement)("div",{className:"mt-1 font-mono text-gray-400 truncate w-64",title:e.ua},e.ua))),!e.is_current&&(0,n.createElement)(a.Button,{variant:"link",isDestructive:!0,onClick:()=>(async e=>{if(confirm((0,l.__)("Are you sure you want to log out this session?","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/sessions/destroy",method:"POST",data:{verifier:e}}),d()}catch(e){alert(e.message||(0,l.__)("Failed to destroy session.","nhrrob-secure"))}})(e.verifier)},(0,l.__)("Logout","nhrrob-secure")))))):(0,n.createElement)("p",null,(0,l.__)("No active sessions found.","nhrrob-secure"))),t.length>1&&(0,n.createElement)("div",{className:"mt-4 pt-3 border-t"},(0,n.createElement)(a.Button,{variant:"secondary",isDestructive:!0,onClick:async()=>{if(confirm((0,l.__)("Are you sure you want to log out all other devices?","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/sessions/destroy-others",method:"POST"}),d(),alert((0,l.__)("All other sessions logged out.","nhrrob-secure"))}catch(e){alert(e.message||(0,l.__)("Failed to destroy sessions.","nhrrob-secure"))}},className:"w-full justify-center"},(0,l.__)("Log Out All Other Devices","nhrrob-secure")))))},p=({settings:e,updateSetting:r})=>{const[t,c]=(0,s.useState)([]),[i,u]=(0,s.useState)(!0),[m,h]=(0,s.useState)(0),[d,b]=(0,s.useState)(1);(0,s.useEffect)(()=>{_()},[d]);const _=async()=>{u(!0);try{const e=20*(d-1),r=await o()({path:`/nhrrob-secure/v1/logs?limit=20&offset=${e}`});c(r.items),h(r.total)}catch(e){console.error(e)}finally{u(!1)}},g=Math.ceil(m/20);return(0,n.createElement)(a.Card,{className:"nhrrob-secure-card nhrrob-secure-audit-log-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Activity Audit Log","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-secure-card-header-actions"},e&&(0,n.createElement)(a.SelectControl,{className:"nhrrob-secure-retention-select",value:e.nhrrob_secure_log_retention_days,options:[{label:(0,l.__)("Keep logs: 7 days","nhrrob-secure"),value:7},{label:(0,l.__)("Keep logs: 30 days","nhrrob-secure"),value:30},{label:(0,l.__)("Keep logs: 90 days","nhrrob-secure"),value:90},{label:(0,l.__)("Keep logs: 1 year","nhrrob-secure"),value:365}],onChange:e=>r("nhrrob_secure_log_retention_days",parseInt(e))}),(0,n.createElement)(a.Button,{variant:"primary",onClick:_,disabled:i,isBusy:i,icon:"update",iconPosition:"right"},(0,l.__)("Refresh","nhrrob-secure")))),i&&(0,n.createElement)("div",{className:"nhrrob-secure-loading-overlay"},(0,n.createElement)(a.Spinner,null)),(0,n.createElement)("div",{className:"nhrrob-secure-audit-table-wrapper"},(0,n.createElement)("table",{className:"nhrrob-secure-audit-table"},(0,n.createElement)("thead",null,(0,n.createElement)("tr",null,(0,n.createElement)("th",null,(0,l.__)("Date","nhrrob-secure")),(0,n.createElement)("th",null,(0,l.__)("User","nhrrob-secure")),(0,n.createElement)("th",null,(0,l.__)("Context","nhrrob-secure")),(0,n.createElement)("th",null,(0,l.__)("Action","nhrrob-secure")),(0,n.createElement)("th",null,(0,l.__)("Item","nhrrob-secure")),(0,n.createElement)("th",null,(0,l.__)("IP Address","nhrrob-secure")))),(0,n.createElement)("tbody",null,t.length>0?t.map(e=>(0,n.createElement)("tr",{key:e.id,className:`severity-${e.severity}`},(0,n.createElement)("td",null,new Date(e.date).toLocaleString()),(0,n.createElement)("td",null,e.user),(0,n.createElement)("td",null,(0,n.createElement)("span",{className:"nhrrob-secure-badge"},e.context)),(0,n.createElement)("td",null,e.action),(0,n.createElement)("td",null,e.label),(0,n.createElement)("td",null,e.ip))):(0,n.createElement)("tr",null,(0,n.createElement)("td",{colSpan:"6",className:"no-logs"},!i&&(0,l.__)("No activity logs found.","nhrrob-secure")))))),g>1&&(0,n.createElement)("div",{className:"nhrrob-secure-pagination"},(0,n.createElement)(a.Button,{isSmall:!0,disabled:1===d||i,onClick:()=>b(d-1)},"« ",(0,l.__)("Prev","nhrrob-secure")),(0,n.createElement)("span",{className:"nhrrob-secure-page-info"},(0,l.__)("Page","nhrrob-secure")," ",d," ",(0,l.__)("of","nhrrob-secure")," ",g),(0,n.createElement)(a.Button,{isSmall:!0,disabled:d===g||i,onClick:()=>b(d+1)},(0,l.__)("Next","nhrrob-secure")," »"))))},v=document.getElementById("nhrrob-secure-settings-root");v&&(0,s.render)((0,n.createElement)(()=>{const[e,r]=(0,s.useState)(null),[t,c]=(0,s.useState)(!0),[d,v]=(0,s.useState)(!1),[y,f]=(0,s.useState)(null);(0,s.useEffect)(()=>{N()},[]);const N=async()=>{try{const e=await o()({path:"/nhrrob-secure/v1/settings"});r(e),c(!1)}catch(e){f({type:"error",message:(0,l.__)("Failed to load settings","nhrrob-secure")}),c(!1)}},w=(t,n)=>{r({...e,[t]:n})};return(0,s.useEffect)(()=>{e?.nhrrob_secure_dark_mode?document.body.classList.add("nhrrob-secure-dark-mode-active"):document.body.classList.remove("nhrrob-secure-dark-mode-active")},[e?.nhrrob_secure_dark_mode]),t?(0,n.createElement)("div",{className:"nhrrob-secure-loading"},(0,n.createElement)(a.Spinner,null)):(0,n.createElement)("div",{className:"nhrrob-secure-settings "+(e.nhrrob_secure_dark_mode?"dark-mode":"")},(0,n.createElement)("div",{className:"nhrrob-secure-header"},(0,n.createElement)("div",{className:"nhrrob-secure-header-main"},(0,n.createElement)("h1",null,(0,l.__)("NHR Secure Settings","nhrrob-secure")),(0,n.createElement)(a.Button,{className:"nhrrob-secure-dark-mode-toggle",icon:e.nhrrob_secure_dark_mode?(0,n.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",width:"20",height:"20"},(0,n.createElement)("path",{d:"M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58a.996.996 0 00-1.41 0 .996.996 0 000 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41L5.99 4.58zm12.37 12.37a.996.996 0 00-1.41 0 .996.996 0 000 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41l-1.06-1.06zm1.06-10.96a.996.996 0 00-1.41-1.41l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06zM7.05 18.36a.996.996 0 00-1.41-1.41l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06z"})):(0,n.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",width:"20",height:"20"},(0,n.createElement)("path",{d:"M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z"})),onClick:async()=>{const r=!e.nhrrob_secure_dark_mode;w("nhrrob_secure_dark_mode",r);try{await o()({path:"/nhrrob-secure/v1/settings",method:"POST",data:{...e,nhrrob_secure_dark_mode:r}})}catch(e){console.error("Failed to save dark mode preference",e)}},label:(0,l.__)("Toggle Dark Mode","nhrrob-secure")})),(0,n.createElement)("p",{className:"nhrrob-secure-subtitle"},(0,l.__)("Configure security features for your WordPress site","nhrrob-secure"))),y&&(0,n.createElement)(a.Notice,{status:y.type,isDismissible:!0,onRemove:()=>f(null)},y.message),(0,n.createElement)("div",{className:"nhrrob-secure-cards"},(0,n.createElement)(i,{settings:e,updateSetting:w}),(0,n.createElement)(u,{settings:e,updateSetting:w}),(0,n.createElement)(m,{settings:e,updateSetting:w}),(0,n.createElement)(g,{settings:e,updateSetting:w}),(0,n.createElement)(h,{settings:e,updateSetting:w}),(0,n.createElement)(b,null),(0,n.createElement)(_,null),(0,n.createElement)(E,{settings:e,updateSetting:w}),(0,n.createElement)(p,{settings:e,updateSetting:w})),(0,n.createElement)("div",{className:"nhrrob-secure-actions"},(0,n.createElement)(a.Button,{variant:"primary",onClick:async()=>{v(!0),f(null);try{await o()({path:"/nhrrob-secure/v1/settings",method:"POST",data:e}),f({type:"success",message:(0,l.__)("Settings saved successfully!","nhrrob-secure")})}catch(e){f({type:"error",message:(0,l.__)("Failed to save settings","nhrrob-secure")})}finally{v(!1)}},isBusy:d,disabled:d},d?(0,l.__)("Saving...","nhrrob-secure"):(0,l.__)("Save Settings","nhrrob-secure"))))},null),v)}},t={};function n(e){var s=t[e];if(void 0!==s)return s.exports;var a=t[e]={exports:{}};return r[e](a,a.exports,n),a.exports}n.m=r,e=[],n.O=(r,t,s,a)=>{if(!t){var l=1/0;for(u=0;u<e.length;u++){for(var[t,s,a]=e[u],c=!0,o=0;o<t.length;o++)(!1&a||l>=a)&&Object.keys(n.O).every(e=>n.O[e](t[o]))?t.splice(o--,1):(c=!1,a<l&&(l=a));if(c){e.splice(u--,1);var i=s();void 0!==i&&(r=i)}}return r}a=a||0;for(var u=e.length;u>0&&e[u-1][2]>a;u--)e[u]=e[u-1];e[u]=[t,s,a]},n.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return n.d(r,{a:r}),r},n.d=(e,r)=>{for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),(()=>{var e={884:0,15:0};n.O.j=r=>0===e[r];var r=(r,t)=>{var s,a,[l,c,o]=t,i=0;if(l.some(r=>0!==e[r])){for(s in c)n.o(c,s)&&(n.m[s]=c[s]);if(o)var u=o(n)}for(r&&r(t);i<l.length;i++)a=l[i],n.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return n.O(u)},t=globalThis.webpackChunknhrrob_secure=globalThis.webpackChunknhrrob_secure||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})();var s=n.O(void 0,[15],()=>n(195));s=n.O(s)})(); -
nhrrob-secure/tags/1.2.0/build/profile.asset.php
r3436910 r3441244 1 <?php return array('dependencies' => array(), 'version' => ' 60edf98ad68210cc7955');1 <?php return array('dependencies' => array(), 'version' => 'b365bbc000a0d9a2f03a'); -
nhrrob-secure/tags/1.2.0/build/profile.css
r3436910 r3441244 280 280 margin-bottom: 1rem 281 281 } 282 .ml-2 { 283 284 margin-left: 0.5rem 285 } 282 286 .ml-5 { 283 287 … … 288 292 margin-top: 0px 289 293 } 294 .mt-1 { 295 296 margin-top: 0.25rem 297 } 290 298 .mt-4 { 291 299 292 300 margin-top: 1rem 293 301 } 302 .block { 303 304 display: block 305 } 306 .flex { 307 308 display: flex 309 } 294 310 .table { 295 311 … … 304 320 display: none 305 321 } 322 .w-64 { 323 324 width: 16rem 325 } 326 .w-full { 327 328 width: 100% 329 } 306 330 .grid-cols-2 { 307 331 308 332 grid-template-columns: repeat(2, minmax(0, 1fr)) 309 333 } 334 .items-start { 335 336 align-items: flex-start 337 } 338 .justify-center { 339 340 justify-content: center 341 } 342 .justify-between { 343 344 justify-content: space-between 345 } 310 346 .gap-2 { 311 347 312 348 gap: 0.5rem 313 349 } 350 .truncate { 351 352 overflow: hidden; 353 354 text-overflow: ellipsis; 355 356 white-space: nowrap 357 } 358 .rounded { 359 360 border-radius: 0.25rem 361 } 362 .rounded-full { 363 364 border-radius: 9999px 365 } 366 .border { 367 368 border-width: 1px 369 } 314 370 .border-t { 315 371 316 372 border-top-width: 1px 317 373 } 374 .border-blue-200 { 375 376 --tw-border-opacity: 1; 377 378 border-color: rgb(191 219 254 / var(--tw-border-opacity, 1)) 379 } 318 380 .border-gray-100 { 319 381 … … 322 384 border-color: rgb(243 244 246 / var(--tw-border-opacity, 1)) 323 385 } 386 .border-gray-200 { 387 388 --tw-border-opacity: 1; 389 390 border-color: rgb(229 231 235 / var(--tw-border-opacity, 1)) 391 } 392 .bg-blue-100 { 393 394 --tw-bg-opacity: 1; 395 396 background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1)) 397 } 398 .bg-blue-50 { 399 400 --tw-bg-opacity: 1; 401 402 background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1)) 403 } 404 .bg-gray-50 { 405 406 --tw-bg-opacity: 1; 407 408 background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1)) 409 } 410 .p-3 { 411 412 padding: 0.75rem 413 } 414 .px-2 { 415 416 padding-left: 0.5rem; 417 418 padding-right: 0.5rem 419 } 420 .py-0\.5 { 421 422 padding-top: 0.125rem; 423 424 padding-bottom: 0.125rem 425 } 426 .pt-3 { 427 428 padding-top: 0.75rem 429 } 324 430 .pt-4 { 325 431 326 432 padding-top: 1rem 327 433 } 434 .font-mono { 435 436 font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace 437 } 328 438 .text-sm { 329 439 … … 338 448 line-height: 1rem 339 449 } 450 .font-medium { 451 452 font-weight: 500 453 } 340 454 .font-semibold { 341 455 342 456 font-weight: 600 343 457 } 458 .text-blue-800 { 459 460 --tw-text-opacity: 1; 461 462 color: rgb(30 64 175 / var(--tw-text-opacity, 1)) 463 } 464 .text-gray-400 { 465 466 --tw-text-opacity: 1; 467 468 color: rgb(156 163 175 / var(--tw-text-opacity, 1)) 469 } 344 470 .text-gray-500 { 345 471 … … 348 474 color: rgb(107 114 128 / var(--tw-text-opacity, 1)) 349 475 } 476 .text-gray-700 { 477 478 --tw-text-opacity: 1; 479 480 color: rgb(55 65 81 / var(--tw-text-opacity, 1)) 481 } 350 482 .filter { 351 483 -
nhrrob-secure/tags/1.2.0/includes/Admin/Api.php
r3438122 r3441244 90 90 'sanitize_callback' => 'rest_sanitize_boolean', 91 91 ], 92 'nhrrob_secure_log_retention_days' => [ 93 'type' => 'integer', 94 'sanitize_callback' => 'absint', 95 ], 96 'nhrrob_secure_disable_xmlrpc' => [ 97 'type' => 'boolean', 98 'sanitize_callback' => 'rest_sanitize_boolean', 99 ], 100 'nhrrob_secure_disable_file_editor' => [ 101 'type' => 'boolean', 102 'sanitize_callback' => 'rest_sanitize_boolean', 103 ], 104 'nhrrob_secure_hide_wp_version' => [ 105 'type' => 'boolean', 106 'sanitize_callback' => 'rest_sanitize_boolean', 107 ], 108 'nhrrob_secure_disable_rest_users' => [ 109 'type' => 'boolean', 110 'sanitize_callback' => 'rest_sanitize_boolean', 111 ], 112 'nhrrob_secure_firewall_blocked_uas' => [ 113 'type' => 'string', 114 'sanitize_callback' => 'sanitize_textarea_field', 115 ], 116 'nhrrob_secure_idle_timeout' => [ 117 'type' => 'integer', 118 'sanitize_callback' => 'absint', 119 ], 92 120 ], 93 121 ]); … … 161 189 ]); 162 190 191 // Get audit logs 192 register_rest_route('nhrrob-secure/v1', '/logs', [ 193 'methods' => 'GET', 194 'callback' => [$this, 'get_logs'], 195 'permission_callback' => function () { 196 return current_user_can('manage_options'); 197 }, 198 ]); 199 200 // Get sessions 201 register_rest_route('nhrrob-secure/v1', '/sessions', [ 202 'methods' => 'GET', 203 'callback' => [$this, 'get_sessions_list'], 204 'permission_callback' => function () { 205 return current_user_can('manage_options'); 206 }, 207 ]); 208 209 // Destroy session 210 register_rest_route('nhrrob-secure/v1', '/sessions/destroy', [ 211 'methods' => 'POST', 212 'callback' => [$this, 'destroy_session'], 213 'permission_callback' => function () { 214 return current_user_can('manage_options'); 215 }, 216 'args' => [ 217 'verifier' => [ 218 'required' => true, 219 'type' => 'string', 220 'sanitize_callback' => 'sanitize_text_field', 221 ], 222 ], 223 ]); 224 225 // Destroy other sessions 226 register_rest_route('nhrrob-secure/v1', '/sessions/destroy-others', [ 227 'methods' => 'POST', 228 'callback' => [$this, 'destroy_other_sessions'], 229 'permission_callback' => function () { 230 return current_user_can('manage_options'); 231 }, 232 ]); 163 233 } 164 234 … … 179 249 'nhrrob_secure_2fa_type' => get_option('nhrrob_secure_2fa_type', 'app'), 180 250 'nhrrob_secure_dark_mode' => (bool) get_option('nhrrob_secure_dark_mode', false), 251 'nhrrob_secure_log_retention_days' => (int) get_option('nhrrob_secure_log_retention_days', 30), 252 'nhrrob_secure_disable_xmlrpc' => (bool) get_option('nhrrob_secure_disable_xmlrpc', false), 253 'nhrrob_secure_disable_file_editor' => (bool) get_option('nhrrob_secure_disable_file_editor', false), 254 'nhrrob_secure_hide_wp_version' => (bool) get_option('nhrrob_secure_hide_wp_version', false), 255 'nhrrob_secure_disable_rest_users' => (bool) get_option('nhrrob_secure_disable_rest_users', false), 256 'nhrrob_secure_firewall_blocked_uas' => get_option('nhrrob_secure_firewall_blocked_uas', ''), 257 'nhrrob_secure_idle_timeout' => (int) get_option('nhrrob_secure_idle_timeout', 0), 181 258 'available_roles' => $this->get_available_roles(), 182 259 ]; … … 268 345 $scanner = new \NHRRob\Secure\FileScanner(); 269 346 $result = $scanner->repair_core_file($file); 270 347 271 348 if (is_wp_error($result)) { 272 349 return $result; 273 350 } 274 351 275 352 return ['success' => true, 'message' => 'File repaired successfully.']; 276 353 } … … 283 360 $file = $request->get_param('file'); 284 361 $scanner = new \NHRRob\Secure\FileScanner(); 285 362 286 363 // Security check: ensure file is inside WP_CONTENT_DIR 287 364 if (strpos($file, WP_CONTENT_DIR) !== 0) { … … 290 367 291 368 if ($scanner->delete_file($file)) { 292 return ['success' => true, 'message' => 'File deleted successfully.'];293 } 294 369 return ['success' => true, 'message' => 'File deleted successfully.']; 370 } 371 295 372 return new \WP_Error('delete_failed', 'Could not delete file.'); 296 373 } 374 375 /** 376 * Get audit logs 377 */ 378 public function get_logs($request) 379 { 380 $limit = $request->get_param('limit') ? (int) $request->get_param('limit') : 20; 381 $offset = $request->get_param('offset') ? (int) $request->get_param('offset') : 0; 382 383 $audit_log = new \NHRRob\Secure\AuditLog(); 384 return $audit_log->get_logs($limit, $offset); 385 } 386 /** 387 * Get sessions list 388 */ 389 public function get_sessions_list() 390 { 391 $manager = new \NHRRob\Secure\SessionManager(); 392 $sessions = $manager->get_sessions(get_current_user_id()); 393 $current_token = wp_get_session_token(); 394 395 $formatted = []; 396 foreach ($sessions as $verifier => $session) { 397 $formatted[] = [ 398 'verifier' => $verifier, 399 'ip' => $session['ip'], 400 'ua' => $session['ua'], 401 'login' => $session['login'], 402 'expiration' => $session['expiration'], 403 'is_current' => $verifier === $current_token, 404 ]; 405 } 406 407 return $formatted; 408 } 409 410 /** 411 * Destroy session 412 */ 413 public function destroy_session($request) 414 { 415 $verifier = $request->get_param('verifier'); 416 $manager = new \NHRRob\Secure\SessionManager(); 417 $manager->destroy_session(get_current_user_id(), $verifier); 418 419 return ['success' => true]; 420 } 421 422 /** 423 * Destroy other sessions 424 */ 425 public function destroy_other_sessions() 426 { 427 $manager = new \NHRRob\Secure\SessionManager(); 428 $manager->destroy_other_sessions(get_current_user_id()); 429 430 return ['success' => true]; 431 } 297 432 } -
nhrrob-secure/tags/1.2.0/includes/App.php
r3435758 r3441244 6 6 * App base class 7 7 */ 8 class App { 8 class App 9 { 10 /** 11 * Initialize the class 12 */ 13 public function __construct() 14 { 15 // Base init 16 } 17 9 18 /** 10 19 * Render a template … … 13 22 * @param array $args 14 23 */ 15 public function render( $name, $args = [] ) { 16 extract( $args ); 24 public function render($name, $args = []) 25 { 26 extract($args); 17 27 $template = NHRROB_SECURE_PATH . '/templates/' . $name . '.php'; 18 28 19 if ( file_exists( $template )) {29 if (file_exists($template)) { 20 30 include $template; 21 31 } -
nhrrob-secure/tags/1.2.0/nhrrob-secure.php
r3438122 r3441244 1 1 <?php 2 2 /** 3 * Plugin Name: NHR Secure – Hide Admin, Limit Login, 2FA & Vulnerability Checker3 * Plugin Name: NHR Secure – Login Security, Firewall, 2FA & Audit Log 4 4 * Plugin URI: http://wordpress.org/plugins/nhrrob-secure/ 5 5 * Description: Lightweight WordPress security plugin that protects your admin area, hides debug logs, limits login attempts, and checks for vulnerabilities. Minimal code, maximum protection. 6 6 * Author: Nazmul Hasan Robin 7 7 * Author URI: https://profiles.wordpress.org/nhrrob/ 8 * Version: 1. 1.08 * Version: 1.2.0 9 9 * Requires at least: 6.0 10 10 * Requires PHP: 7.4 … … 31 31 * @var string 32 32 */ 33 const version = '1. 1.0';33 const version = '1.2.0'; 34 34 35 35 /** … … 103 103 new \NHRRob\Secure\FileScanner(); 104 104 105 // Initialize hardening and firewall 106 new \NHRRob\Secure\Hardening(); 107 108 // Initialize session manager 109 new \NHRRob\Secure\SessionManager(); 110 111 // Initialize audit log 112 new \NHRRob\Secure\AuditLog(); 113 105 114 // Initialize admin menu 106 115 if (is_admin()) { … … 119 128 wp_schedule_event(time(), 'daily', 'nhrrob_secure_vulnerability_scan_cron'); 120 129 } 130 131 if (!wp_next_scheduled('nhrrob_secure_daily_cleanup')) { 132 wp_schedule_event(time(), 'daily', 'nhrrob_secure_daily_cleanup'); 133 } 134 135 // Create audit log table 136 (new \NHRRob\Secure\AuditLog())->maybe_install_schema(); 121 137 } 122 138 … … 129 145 { 130 146 wp_clear_scheduled_hook('nhrrob_secure_vulnerability_scan_cron'); 147 wp_clear_scheduled_hook('nhrrob_secure_daily_cleanup'); 131 148 } 132 149 } -
nhrrob-secure/tags/1.2.0/readme.txt
r3438122 r3441244 1 === NHR Secure – Hide Admin, Limit Login, 2FA & Vulnerability Checker===1 === NHR Secure – Login Security, Firewall, 2FA & Audit Log === 2 2 Contributors: nhrrob 3 3 Tags: security, hide admin, login protection, debug log, 2fa … … 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 1. 1.07 Stable tag: 1.2.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 56 56 - Check file integrity 57 57 58 ### 🖥️ User Session Management 59 Monitor and control active user sessions to prevent unauthorized access. 60 - **View Active Sessions:** See IP, location, device, and login time for all logged-in users. 61 - **Remote Logout:** Instantly log out suspicious sessions or all other devices. 62 - **Idle Timeout:** Automatically log out inactive users after a set period. 63 64 ### 🧱 Hardening & Firewall 65 Essential security hardening to lock down your WordPress site. 66 - **Disable XML-RPC:** Prevent remote attacks and brute-force attempts. 67 - **Disable File Editor:** Stop file modifications from the dashboard. 68 - **Hide WP Version:** Obscure your WordPress version from attackers. 69 - **Block User-Agents:** Prevent bad bots and scrapers from accessing your site. 70 - **Disable User Enumeration:** Stop attackers from harvesting usernames via REST API. 71 72 ### 📝 Activity Audit Log 73 Keep a record of important security events on your site. 74 - Tracks logins, failed attempts, file changes, and settings updates. 75 - View user, IP, and event details. 76 - Configurable log retention policy. 77 58 78 ### ⚡ Lightweight & Minimal 59 79 Designed to deliver maximum security with minimal code. No bloat, no complexity. … … 104 124 == Changelog == 105 125 126 = 1.2.0 - 17/01/2026 = 127 - Added: User Session Management (View active sessions, remote logout, idle timeout) 128 - Added: Hardening & Firewall (Disable XML-RPC, File Editor, Version Hiding, User Enumeration) 129 - Added: User-Agent Blocking 130 - Added: Audit Logs for security events 131 - Fixed: Dark mode improvements 132 - Improved: UI enhancements 133 106 134 = 1.1.0 - 13/01/2026 = 107 135 - Added: Vulnerability Checker -
nhrrob-secure/trunk/assets/src/components/VulnerabilityChecker.js
r3438122 r3441244 115 115 <a href="plugins.php" style={{ textDecoration: 'none', color: 'inherit' }}> 116 116 {decodeEntities(plugin.name)} 117 </a> 117 </a> 118 118 <span style={{ fontWeight: 'normal', color: '#666' }}> ({plugin.version})</span> 119 119 </strong> -
nhrrob-secure/trunk/assets/src/index.js
r3438122 r3441244 13 13 import VulnerabilityChecker from './components/VulnerabilityChecker'; 14 14 import FileScanner from './components/FileScanner'; 15 import Hardening from './components/Hardening'; 16 import SessionManager from './components/SessionManager'; 17 import AuditLog from './components/AuditLog'; 15 18 import './style.css'; 16 19 … … 124 127 <CustomLoginPage settings={settings} updateSetting={updateSetting} /> 125 128 <TwoFactorAuth settings={settings} updateSetting={updateSetting} /> 129 <Hardening settings={settings} updateSetting={updateSetting} /> 126 130 <FileProtection settings={settings} updateSetting={updateSetting} /> 127 131 <VulnerabilityChecker /> 128 132 <FileScanner /> 133 <SessionManager settings={settings} updateSetting={updateSetting} /> 134 <AuditLog settings={settings} updateSetting={updateSetting} /> 129 135 </div> 130 136 … … 148 154 render(<SettingsApp />, rootElement); 149 155 } 150 -
nhrrob-secure/trunk/assets/src/style.css
r3438122 r3441244 134 134 } 135 135 136 .dark-mode .components-text-control__input { 136 .dark-mode .components-text-control__input, 137 .dark-mode .components-textarea-control__input { 137 138 background-color: #2c3338 !important; 138 139 border-color: #43494e !important; 139 140 color: #f0f0f1 !important; 141 } 142 143 .dark-mode .components-placeholder__input::placeholder, 144 .dark-mode input::placeholder, 145 .dark-mode textarea::placeholder { 146 color: rgba(240, 240, 241, 0.6) !important; 147 } 148 149 /* Session Manager Dark Mode */ 150 .dark-mode .session-item.bg-gray-50 { 151 background-color: rgba(255, 255, 255, 0.03) !important; 152 border-color: var(--nhrrob-secure-border) !important; 153 } 154 155 .dark-mode .session-item.bg-blue-50 { 156 background-color: rgba(34, 113, 177, 0.15) !important; 157 border-color: var(--nhrrob-secure-border) !important; 158 } 159 160 .dark-mode .session-item .text-gray-700 { 161 color: var(--nhrrob-secure-text) !important; 162 } 163 164 .dark-mode .session-item .text-gray-500 { 165 color: var(--nhrrob-secure-text-muted) !important; 166 } 167 168 .dark-mode .session-item .bg-blue-100 { 169 background-color: rgba(34, 113, 177, 0.3) !important; 170 color: #72aee6 !important; 171 } 172 173 /* Hardening Headers */ 174 .nhrrob-secure-setting-subtitle { 175 @apply text-sm font-semibold mb-3 mt-0 uppercase tracking-wide opacity-80; 176 color: var(--nhrrob-secure-text-muted); 177 } 178 179 .dark-mode .nhrrob-secure-setting-subtitle { 180 color: #a7aaad; 140 181 } 141 182 … … 358 399 } 359 400 } 401 402 /* Retention Select */ 403 .nhrrob-secure-retention-select select { 404 @apply h-8 py-0 pr-8 pl-2 text-xs border-gray-300; 405 border-color: var(--nhrrob-secure-border); 406 color: var(--nhrrob-secure-text); 407 background-color: var(--nhrrob-secure-bg); 408 } 409 410 .nhrrob-secure-settings.dark-mode .nhrrob-secure-retention-select select { 411 background-color: #2c3338 !important; 412 /* Darker input bg */ 413 border-color: var(--nhrrob-secure-border) !important; 414 color: var(--nhrrob-secure-text) !important; 415 } 416 417 .nhrrob-secure-retention-select .components-base-control__field { 418 @apply mb-0; 419 } 420 421 422 423 /* Audit Log Table */ 424 .nhrrob-secure-audit-table-wrapper { 425 @apply overflow-x-auto border rounded mt-5; 426 border-color: var(--nhrrob-secure-border); 427 } 428 429 .nhrrob-secure-audit-table { 430 @apply w-full border-collapse text-[13px]; 431 background: var(--nhrrob-secure-card-bg); 432 color: var(--nhrrob-secure-text-muted); 433 } 434 435 .nhrrob-secure-audit-table th, 436 .nhrrob-secure-audit-table td { 437 @apply p-3 text-left border-b; 438 border-color: var(--nhrrob-secure-border); 439 } 440 441 .nhrrob-secure-audit-table th { 442 @apply font-semibold; 443 background-color: var(--nhrrob-secure-bg); 444 color: var(--nhrrob-secure-text); 445 } 446 447 .nhrrob-secure-audit-table tr:last-child td { 448 @apply border-b-0; 449 } 450 451 .nhrrob-secure-audit-table tr:hover td { 452 background-color: var(--nhrrob-secure-bg); 453 } 454 455 .nhrrob-secure-badge { 456 @apply px-1.5 py-0.5 rounded text-[11px] uppercase font-medium; 457 background-color: var(--nhrrob-secure-bg); 458 color: var(--nhrrob-secure-text); 459 } 460 461 /* Dark Mode support for table */ 462 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table-wrapper { 463 border-color: #3c434a; 464 } 465 466 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table { 467 background: #1e1e1e; 468 color: #dcdcde; 469 } 470 471 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table th { 472 background: #2c2c2c; 473 color: #ffffff; 474 border-bottom-color: #3c434a; 475 } 476 477 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table td { 478 border-bottom-color: #3c434a; 479 } 480 481 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table tr:hover td { 482 background: #2c2c2c; 483 } 484 485 .nhrrob-secure-settings.dark-mode .nhrrob-secure-badge { 486 background: #3c434a; 487 color: #dcdcde; 488 } 489 490 .nhrrob-secure-pagination { 491 @apply flex justify-center items-center gap-4 mt-5; 492 } 493 494 .nhrrob-secure-page-info { 495 @apply text-[13px]; 496 color: var(--nhrrob-secure-text-muted); 497 } 498 499 .nhrrob-secure-settings.dark-mode .nhrrob-secure-page-info { 500 color: #a7aaad; 501 } 502 503 .no-logs { 504 @apply text-center p-8 !important; 505 color: var(--nhrrob-secure-text-muted); 506 } 507 508 /* Severity indicators */ 509 .severity-2 td:first-child { 510 @apply border-l-4 border-l-yellow-400; 511 } 512 513 .severity-3 td:first-child { 514 @apply border-l-4 border-l-red-600; 515 } -
nhrrob-secure/trunk/build/admin.asset.php
r3438122 r3441244 1 <?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-components', 'wp-element', 'wp-html-entities', 'wp-i18n'), 'version' => ' e9b337e5f5ffe2cea663');1 <?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-components', 'wp-element', 'wp-html-entities', 'wp-i18n'), 'version' => '876f03e1a6accd816f8d'); -
nhrrob-secure/trunk/build/admin.css
r3438122 r3441244 161 161 justify-content: space-between; 162 162 gap: 1rem; 163 } 164 165 .nhrrob-secure-card-header-actions { 166 display: flex; 167 align-items: center; 168 gap: 0.75rem; 163 169 } 164 170 … … 181 187 } 182 188 183 .dark-mode .components-text-control__input { 189 .dark-mode .components-text-control__input, 190 .dark-mode .components-textarea-control__input { 184 191 background-color: #2c3338 !important; 185 192 border-color: #43494e !important; 186 193 color: #f0f0f1 !important; 194 } 195 196 .dark-mode .components-placeholder__input::-moz-placeholder, .dark-mode input::-moz-placeholder, .dark-mode textarea::-moz-placeholder { 197 color: rgba(240, 240, 241, 0.6) !important; 198 } 199 200 .dark-mode .components-placeholder__input::placeholder, 201 .dark-mode input::placeholder, 202 .dark-mode textarea::placeholder { 203 color: rgba(240, 240, 241, 0.6) !important; 204 } 205 206 /* Session Manager Dark Mode */ 207 .dark-mode .session-item.bg-gray-50 { 208 background-color: rgba(255, 255, 255, 0.03) !important; 209 border-color: var(--nhrrob-secure-border) !important; 210 } 211 212 .dark-mode .session-item.bg-blue-50 { 213 background-color: rgba(34, 113, 177, 0.15) !important; 214 border-color: var(--nhrrob-secure-border) !important; 215 } 216 217 .dark-mode .session-item .text-gray-700 { 218 color: var(--nhrrob-secure-text) !important; 219 } 220 221 .dark-mode .session-item .text-gray-500 { 222 color: var(--nhrrob-secure-text-muted) !important; 223 } 224 225 .dark-mode .session-item .bg-blue-100 { 226 background-color: rgba(34, 113, 177, 0.3) !important; 227 color: #72aee6 !important; 228 } 229 230 /* Hardening Headers */ 231 .nhrrob-secure-setting-subtitle { 232 margin-bottom: 0.75rem; 233 margin-top: 0px; 234 font-size: 0.875rem; 235 line-height: 1.25rem; 236 font-weight: 600; 237 text-transform: uppercase; 238 letter-spacing: 0.025em; 239 opacity: 0.8; 240 color: var(--nhrrob-secure-text-muted); 241 } 242 243 .dark-mode .nhrrob-secure-setting-subtitle { 244 color: #a7aaad; 187 245 } 188 246 … … 394 452 } 395 453 454 .dark-mode .session-item .nhrrob-secure-card-subtitle { 455 color: var(--nhrrob-secure-text-muted); 456 } 457 396 458 .nhrrob-secure-card-subtitle { 397 459 margin: 0px; … … 424 486 background-color: transparent; 425 487 } 488 489 .dark-mode .session-item.nhrrob-result-group-title { 490 background-color: rgba(255, 255, 255, 0.03); 491 border-color: var(--nhrrob-secure-border); 492 } 426 493 427 494 .nhrrob-result-group-title { … … 471 538 } 472 539 540 .dark-mode .nhrrob-result-row:hover.session-item { 541 background-color: rgba(255, 255, 255, 0.03); 542 border-color: var(--nhrrob-secure-border); 543 } 544 473 545 .nhrrob-result-row:hover { 474 546 --tw-bg-opacity: 1; … … 501 573 color: rgb(229 231 235 / var(--tw-text-opacity, 1)); 502 574 } 575 576 .dark-mode .session-item .nhrrob-file-meta { 577 color: var(--nhrrob-secure-text-muted); 578 } 503 579 504 580 .nhrrob-file-meta { … … 538 614 margin-bottom: 1rem; 539 615 } 616 .ml-2 { 617 margin-left: 0.5rem; 618 } 540 619 .ml-5 { 541 620 margin-left: 1.25rem; … … 544 623 margin-top: 0px; 545 624 } 625 .mt-1 { 626 margin-top: 0.25rem; 627 } 546 628 .mt-4 { 547 629 margin-top: 1rem; 548 630 } 631 .block { 632 display: block; 633 } 634 .flex { 635 display: flex; 636 } 549 637 .table { 550 638 display: table; … … 556 644 display: none; 557 645 } 646 .w-64 { 647 width: 16rem; 648 } 649 .w-full { 650 width: 100%; 651 } 558 652 .grid-cols-2 { 559 653 grid-template-columns: repeat(2, minmax(0, 1fr)); 560 654 } 655 .items-start { 656 align-items: flex-start; 657 } 658 .justify-center { 659 justify-content: center; 660 } 661 .justify-between { 662 justify-content: space-between; 663 } 561 664 .gap-2 { 562 665 gap: 0.5rem; 563 666 } 667 .truncate { 668 overflow: hidden; 669 text-overflow: ellipsis; 670 white-space: nowrap; 671 } 672 .rounded { 673 border-radius: 0.25rem; 674 } 675 .rounded-full { 676 border-radius: 9999px; 677 } 678 .border { 679 border-width: 1px; 680 } 564 681 .border-t { 565 682 border-top-width: 1px; 683 } 684 .border-blue-200 { 685 --tw-border-opacity: 1; 686 border-color: rgb(191 219 254 / var(--tw-border-opacity, 1)); 566 687 } 567 688 .border-gray-100 { … … 569 690 border-color: rgb(243 244 246 / var(--tw-border-opacity, 1)); 570 691 } 692 .border-gray-200 { 693 --tw-border-opacity: 1; 694 border-color: rgb(229 231 235 / var(--tw-border-opacity, 1)); 695 } 696 .bg-blue-100 { 697 --tw-bg-opacity: 1; 698 background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1)); 699 } 700 .bg-blue-50 { 701 --tw-bg-opacity: 1; 702 background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1)); 703 } 704 .bg-gray-50 { 705 --tw-bg-opacity: 1; 706 background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1)); 707 } 708 .p-3 { 709 padding: 0.75rem; 710 } 711 .px-2 { 712 padding-left: 0.5rem; 713 padding-right: 0.5rem; 714 } 715 .py-0\.5 { 716 padding-top: 0.125rem; 717 padding-bottom: 0.125rem; 718 } 719 .pt-3 { 720 padding-top: 0.75rem; 721 } 571 722 .pt-4 { 572 723 padding-top: 1rem; 724 } 725 .font-mono { 726 font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 573 727 } 574 728 .text-sm { … … 580 734 line-height: 1rem; 581 735 } 736 .font-medium { 737 font-weight: 500; 738 } 582 739 .font-semibold { 583 740 font-weight: 600; 584 741 } 742 .text-blue-800 { 743 --tw-text-opacity: 1; 744 color: rgb(30 64 175 / var(--tw-text-opacity, 1)); 745 } 746 .text-gray-400 { 747 --tw-text-opacity: 1; 748 color: rgb(156 163 175 / var(--tw-text-opacity, 1)); 749 } 585 750 .text-gray-500 { 586 751 --tw-text-opacity: 1; 587 752 color: rgb(107 114 128 / var(--tw-text-opacity, 1)); 753 } 754 .text-gray-700 { 755 --tw-text-opacity: 1; 756 color: rgb(55 65 81 / var(--tw-text-opacity, 1)); 588 757 } 589 758 .filter { … … 608 777 } 609 778 } 779 780 /* Retention Select */ 781 .nhrrob-secure-retention-select select { 782 height: 2rem; 783 --tw-border-opacity: 1; 784 border-color: rgb(209 213 219 / var(--tw-border-opacity, 1)); 785 padding-top: 0px; 786 padding-bottom: 0px; 787 padding-right: 2rem; 788 padding-left: 0.5rem; 789 font-size: 0.75rem; 790 line-height: 1rem; 791 border-color: var(--nhrrob-secure-border); 792 color: var(--nhrrob-secure-text); 793 background-color: var(--nhrrob-secure-bg); 794 } 795 796 .nhrrob-secure-settings.dark-mode .nhrrob-secure-retention-select select { 797 background-color: #2c3338 !important; 798 /* Darker input bg */ 799 border-color: var(--nhrrob-secure-border) !important; 800 color: var(--nhrrob-secure-text) !important; 801 } 802 803 .nhrrob-secure-retention-select .components-base-control__field { 804 margin-bottom: 0px; 805 } 806 807 808 809 /* Audit Log Table */ 810 .nhrrob-secure-audit-table-wrapper { 811 margin-top: 1.25rem; 812 overflow-x: auto; 813 border-radius: 0.25rem; 814 border-width: 1px; 815 border-color: var(--nhrrob-secure-border); 816 } 817 818 .nhrrob-secure-audit-table { 819 width: 100%; 820 border-collapse: collapse; 821 font-size: 13px; 822 background: var(--nhrrob-secure-card-bg); 823 color: var(--nhrrob-secure-text-muted); 824 } 825 826 .nhrrob-secure-audit-table th, 827 .nhrrob-secure-audit-table td { 828 border-bottom-width: 1px; 829 padding: 0.75rem; 830 text-align: left; 831 border-color: var(--nhrrob-secure-border); 832 } 833 834 .nhrrob-secure-audit-table th { 835 font-weight: 600; 836 background-color: var(--nhrrob-secure-bg); 837 color: var(--nhrrob-secure-text); 838 } 839 840 .nhrrob-secure-audit-table tr:last-child td { 841 border-bottom-width: 0px; 842 } 843 844 .nhrrob-secure-audit-table tr:hover td { 845 background-color: var(--nhrrob-secure-bg); 846 } 847 848 .nhrrob-secure-badge { 849 border-radius: 0.25rem; 850 padding-left: 0.375rem; 851 padding-right: 0.375rem; 852 padding-top: 0.125rem; 853 padding-bottom: 0.125rem; 854 font-size: 11px; 855 font-weight: 500; 856 text-transform: uppercase; 857 background-color: var(--nhrrob-secure-bg); 858 color: var(--nhrrob-secure-text); 859 } 860 861 /* Dark Mode support for table */ 862 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table-wrapper { 863 border-color: #3c434a; 864 } 865 866 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table { 867 background: #1e1e1e; 868 color: #dcdcde; 869 } 870 871 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table th { 872 background: #2c2c2c; 873 color: #ffffff; 874 border-bottom-color: #3c434a; 875 } 876 877 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table td { 878 border-bottom-color: #3c434a; 879 } 880 881 .nhrrob-secure-settings.dark-mode .nhrrob-secure-audit-table tr:hover td { 882 background: #2c2c2c; 883 } 884 885 .nhrrob-secure-settings.dark-mode .nhrrob-secure-badge { 886 background: #3c434a; 887 color: #dcdcde; 888 } 889 890 .nhrrob-secure-pagination { 891 margin-top: 1.25rem; 892 display: flex; 893 align-items: center; 894 justify-content: center; 895 gap: 1rem; 896 } 897 898 .nhrrob-secure-page-info { 899 font-size: 13px; 900 color: var(--nhrrob-secure-text-muted); 901 } 902 903 .nhrrob-secure-settings.dark-mode .nhrrob-secure-page-info { 904 color: #a7aaad; 905 } 906 907 .no-logs { 908 padding: 2rem !important; 909 text-align: center !important; 910 color: var(--nhrrob-secure-text-muted); 911 } 912 913 /* Severity indicators */ 914 .severity-2 td:first-child { 915 border-left-width: 4px; 916 --tw-border-opacity: 1; 917 border-left-color: rgb(250 204 21 / var(--tw-border-opacity, 1)); 918 } 919 920 .severity-3 td:first-child { 921 border-left-width: 4px; 922 --tw-border-opacity: 1; 923 border-left-color: rgb(220 38 38 / var(--tw-border-opacity, 1)); 924 } -
nhrrob-secure/trunk/build/admin.js
r3438122 r3441244 1 (()=>{"use strict";var e,r={ 967(e,r,t){const n=window.React,a=window.wp.element,s=window.wp.components,l=window.wp.i18n,c=window.wp.apiFetch;var o=t.n(c);const i=({settings:e,updateSetting:r})=>(0,n.createElement)(s.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Login Protection","nhrrob-secure")),(0,n.createElement)(s.ToggleControl,{label:(0,l.__)("Enable Login Attempts Limit","nhrrob-secure"),help:(0,l.__)("Limit failed login attempts to prevent brute force attacks","nhrrob-secure"),checked:e.nhrrob_secure_limit_login_attempts,onChange:e=>r("nhrrob_secure_limit_login_attempts",e)}),e.nhrrob_secure_limit_login_attempts&&(0,n.createElement)(s.TextControl,{label:(0,l.__)("Maximum Login Attempts","nhrrob-secure"),help:(0,l.__)("Number of failed attempts before blocking (default: 5)","nhrrob-secure"),type:"number",value:e.nhrrob_secure_login_attempts_limit,onChange:e=>r("nhrrob_secure_login_attempts_limit",parseInt(e)||5),min:"1",max:"20"}),(0,n.createElement)(s.ToggleControl,{label:(0,l.__)("Enable Proxy IP Detection","nhrrob-secure"),help:(0,l.__)("Detect real IP behind proxies (Cloudflare, etc.)","nhrrob-secure"),checked:e.nhrrob_secure_enable_proxy_ip,onChange:e=>r("nhrrob_secure_enable_proxy_ip",e)}))),u=({settings:e,updateSetting:r})=>(0,n.createElement)(s.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Custom Login Page","nhrrob-secure")),(0,n.createElement)(s.ToggleControl,{label:(0,l.__)("Enable Custom Login URL","nhrrob-secure"),help:(0,l.__)("Hide wp-login.php and use a custom login URL","nhrrob-secure"),checked:e.nhrrob_secure_custom_login_page,onChange:e=>r("nhrrob_secure_custom_login_page",e)}),e.nhrrob_secure_custom_login_page&&(0,n.createElement)(s.TextControl,{label:(0,l.__)("Custom Login URL","nhrrob-secure"),help:(0,l.__)("Your login page will be accessible at this URL","nhrrob-secure"),value:e.nhrrob_secure_custom_login_url,onChange:e=>r("nhrrob_secure_custom_login_url",e),placeholder:"/hidden-access-52w"}),e.nhrrob_secure_custom_login_page&&(0,n.createElement)("div",{className:"nhrrob-secure-info"},(0,n.createElement)("strong",null,(0,l.__)("Your login URL:","nhrrob-secure")),(0,n.createElement)("code",null,window.location.origin,e.nhrrob_secure_custom_login_url)))),m=({settings:e,updateSetting:r})=>{const t=e.nhrrob_secure_2fa_enforced_roles||[],a=e.available_roles||[];return(0,n.createElement)(s.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Two-Factor Authentication","nhrrob-secure")),(0,n.createElement)(s.ToggleControl,{label:(0,l.__)("Enable Global 2FA","nhrrob-secure"),help:(0,n.createElement)(n.Fragment,null,(0,l.__)("Enables Google Authenticator support for all users. Users can set it up in their ","nhrrob-secure"),(0,n.createElement)("a",{href:nhrrobSecureSettings.profile_url,target:"_blank",rel:"noreferrer"},(0,l.__)("profile page","nhrrob-secure")),"."),checked:e.nhrrob_secure_enable_2fa,onChange:e=>r("nhrrob_secure_enable_2fa",e)}),e.nhrrob_secure_enable_2fa&&(0,n.createElement)(n.Fragment,null,(0,n.createElement)("div",{className:"nhrrob-secure-2fa-method pt-4 border-t border-gray-100"},(0,n.createElement)("h3",{className:"text-sm font-semibold mb-3"},(0,l.__)("2FA Method","nhrrob-secure")),(0,n.createElement)(s.RadioControl,{selected:e.nhrrob_secure_2fa_type||"app",options:[{label:(0,l.__)("Authenticator App (Recommended)","nhrrob-secure"),value:"app"},{label:(0,l.__)("Email OTP","nhrrob-secure"),value:"email"}],onChange:e=>r("nhrrob_secure_2fa_type",e)})),(0,n.createElement)("div",{className:"nhrrob-secure-enforced-roles pt-4 border-t border-gray-100"},(0,n.createElement)("h3",{className:"text-sm font-semibold mb-3"},(0,l.__)("Enforced 2FA by Role","nhrrob-secure")),(0,n.createElement)("p",{className:"text-xs text-gray-500 mb-4"},(0,l.__)("Users with the selected roles will be forced to set up 2FA before they can access the admin dashboard.","nhrrob-secure")),(0,n.createElement)("div",{className:"grid grid-cols-2 gap-2"},a.map(e=>(0,n.createElement)(s.CheckboxControl,{key:e.value,label:e.label,checked:t.includes(e.value),onChange:n=>((e,n)=>{const a=n?[...t,e]:t.filter(r=>r!==e);r("nhrrob_secure_2fa_enforced_roles",a)})(e.value,n)})))))))},h=({settings:e,updateSetting:r})=>(0,n.createElement)(s.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("File Protection","nhrrob-secure")),(0,n.createElement)(s.ToggleControl,{label:(0,l.__)("Protect Debug Log","nhrrob-secure"),help:(0,l.__)("Block direct access to wp-content/debug.log","nhrrob-secure"),checked:e.nhrrob_secure_protect_debug_log,onChange:e=>r("nhrrob_secure_protect_debug_log",e)}))),d=window.wp.htmlEntities,b=()=>{const[e,r]=(0,a.useState)(null),[t,c]=(0,a.useState)(!0),[i,u]=(0,a.useState)(!1),[m,h]=(0,a.useState)(null);(0,a.useEffect)(()=>{b()},[]);const b=async()=>{try{const e=await o()({path:"/nhrrob-secure/v1/vulnerability/status"});r(e),c(!1)}catch(e){h((0,l.__)("Failed to fetch vulnerability status","nhrrob-secure")),c(!1)}};if(t)return(0,n.createElement)(s.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)(s.Spinner,null)));const _=e&&(e.core.length>0||e.plugins.length>0||e.themes.length>0);return(0,n.createElement)(s.Card,{className:"nhrrob-secure-card nhrrob-secure-vulnerability-card"},(0,n.createElement)(s.CardBody,null,(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Vulnerability Checker","nhrrob-secure")),(0,n.createElement)(s.Button,{variant:"primary",onClick:async()=>{u(!0),h(null);try{const e=await o()({path:"/nhrrob-secure/v1/vulnerability/scan",method:"POST"});r(e)}catch(e){h((0,l.__)("Failed to run vulnerability scan","nhrrob-secure"))}finally{u(!1)}},isBusy:i,disabled:i,icon:"update",iconPosition:"right"},i?(0,l.__)("Scanning...","nhrrob-secure"):(0,l.__)("Scan Now","nhrrob-secure"))),(0,n.createElement)("p",{className:"nhrrob-secure-last-scan"},(0,n.createElement)("strong",null,(0,l.__)("Last Scan:","nhrrob-secure"))," ",(g=e.last_scan)?new Date(1e3*g).toLocaleString():(0,l.__)("Never","nhrrob-secure")),m&&(0,n.createElement)(s.Notice,{status:"error",isDismissible:!1},m),_?(0,n.createElement)("div",{className:"nhrrob-secure-vulnerability-list"},(0,n.createElement)(s.Notice,{status:"warning",isDismissible:!1},(0,l.__)("Vulnerabilities detected! Please review and update the items below.","nhrrob-secure")),e.core.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("WordPress Core","nhrrob-secure")),(0,n.createElement)("ul",null,e.core.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name))))),e.plugins.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("Plugins","nhrrob-secure")),e.plugins.map((e,r)=>(0,n.createElement)("div",{key:r,className:"vulnerability-item"},(0,n.createElement)("strong",null,(0,n.createElement)("a",{href:"plugins.php",style:{textDecoration:"none",color:"inherit"}},(0,d.decodeEntities)(e.name)),(0,n.createElement)("span",{style:{fontWeight:"normal",color:"#666"}}," (",e.version,")")),(0,n.createElement)("ul",null,e.vulnerabilities.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name))))))),e.themes.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("Themes","nhrrob-secure")),e.themes.map((e,r)=>(0,n.createElement)("div",{key:r,className:"vulnerability-item"},(0,n.createElement)("strong",null,(0,d.decodeEntities)(e.name)," (",e.version,")"),(0,n.createElement)("ul",null,e.vulnerabilities.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name)))))))):(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No known vulnerabilities detected.","nhrrob-secure"))));var g},_=()=>{const[e,r]=(0,a.useState)(!1),[t,c]=(0,a.useState)(null),[i,u]=(0,a.useState)(null),[m,h]=(0,a.useState)("core"),d=async()=>{r(!0),u(null),c(null);try{const e="core"===m?"/nhrrob-secure/v1/scanner/core":"/nhrrob-secure/v1/scanner/malware",r=await o()({path:e,method:"POST"});c(r)}catch(e){u(e.message||(0,l.__)("An error occurred during scan.","nhrrob-secure"))}finally{r(!1)}};return(0,n.createElement)("div",{className:"nhrrob-secure-card nhrrob-secure-vulnerability-card padded-header"},(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("div",{className:"nhrrob-secure-header-content"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("File Scanner","nhrrob-secure")),(0,n.createElement)("p",{className:"nhrrob-secure-card-subtitle"},(0,l.__)("Scan your site for file modifications and potential malware.","nhrrob-secure"))),(0,n.createElement)("div",{className:"nhrrob-scan-controls"},(0,n.createElement)("div",{className:"nhrrob-scan-type-toggle"},(0,n.createElement)("button",{className:"nhrrob-scan-toggle-btn "+("core"===m?"active":""),onClick:()=>h("core"),disabled:e},(0,l.__)("Core Integrity","nhrrob-secure")),(0,n.createElement)("button",{className:"nhrrob-scan-toggle-btn "+("malware"===m?"active":""),onClick:()=>h("malware"),disabled:e},(0,l.__)("Malware Scan","nhrrob-secure"))),(0,n.createElement)(s.Button,{variant:"primary",onClick:()=>d(),isBusy:e,disabled:e,icon:"update",iconPosition:"right"},e?(0,l.__)("Scanning...","nhrrob-secure"):(0,l.__)("Start Scan","nhrrob-secure")))),(0,n.createElement)("div",{className:"nhrrob-card-body"},i&&(0,n.createElement)("div",{className:"notice notice-error inline-notice"},(0,n.createElement)("p",null,i)),t&&(0,n.createElement)("div",{className:"nhrrob-secure-vulnerability-list"},("core"===m&&(t.modified?.length>0||t.missing?.length>0)||"malware"===m&&t.suspicious?.length>0)&&(0,n.createElement)("div",{className:"notice notice-warning inline-notice nhrrob-warning-notice"},(0,n.createElement)("p",null,(0,l.__)("Issues detected! Please review and update the items below.","nhrrob-secure"))),"core"===m&&(0,n.createElement)(n.Fragment,null,t.modified&&t.modified.length>0&&(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Modified Core Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.modified.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e)),(0,n.createElement)(s.Button,{variant:"secondary",isSmall:!0,onClick:()=>(async e=>{if(confirm((0,l.__)("Are you sure you want to repair this file? It will be overwritten with the original version.","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/scanner/repair",method:"POST",data:{file:e}}),alert((0,l.__)("File repaired successfully.","nhrrob-secure")),d()}catch(e){alert(e.message||(0,l.__)("Repair failed.","nhrrob-secure"))}})(e)},(0,l.__)("Repair","nhrrob-secure")))))),t.missing&&t.missing.length>0&&(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Missing Core Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.missing.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e)))))),!t.modified?.length&&!t.missing?.length&&(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No modified core files found.","nhrrob-secure"))),"malware"===m&&(0,n.createElement)(n.Fragment,null,t.suspicious&&t.suspicious.length>0?(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Suspicious Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.suspicious.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e.file),(0,n.createElement)("span",{className:"nhrrob-file-meta"},e.reason)),(0,n.createElement)(s.Button,{variant:"link",isDestructive:!0,onClick:()=>(async e=>{if(confirm((0,l.__)("Are you sure you want to PERMANENTLY delete this file?","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/scanner/delete",method:"POST",data:{file:e}}),alert((0,l.__)("File deleted successfully.","nhrrob-secure")),d()}catch(e){alert(e.message||(0,l.__)("Delete failed.","nhrrob-secure"))}})(e.file)},(0,l.__)("Delete","nhrrob-secure")))))):(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No suspicious files found.","nhrrob-secure")),(0,n.createElement)("p",{className:"description nhrrob-scan-count"},(0,n.createElement)("small",null,(0,l.__)("Scanned files:","nhrrob-secure")," ",t.scanned_count))))))},g=document.getElementById("nhrrob-secure-settings-root");g&&(0,a.render)((0,n.createElement)(()=>{const[e,r]=(0,a.useState)(null),[t,c]=(0,a.useState)(!0),[d,g]=(0,a.useState)(!1),[p,E]=(0,a.useState)(null);(0,a.useEffect)(()=>{v()},[]);const v=async()=>{try{const e=await o()({path:"/nhrrob-secure/v1/settings"});r(e),c(!1)}catch(e){E({type:"error",message:(0,l.__)("Failed to load settings","nhrrob-secure")}),c(!1)}},f=(t,n)=>{r({...e,[t]:n})};return(0,a.useEffect)(()=>{e?.nhrrob_secure_dark_mode?document.body.classList.add("nhrrob-secure-dark-mode-active"):document.body.classList.remove("nhrrob-secure-dark-mode-active")},[e?.nhrrob_secure_dark_mode]),t?(0,n.createElement)("div",{className:"nhrrob-secure-loading"},(0,n.createElement)(s.Spinner,null)):(0,n.createElement)("div",{className:"nhrrob-secure-settings "+(e.nhrrob_secure_dark_mode?"dark-mode":"")},(0,n.createElement)("div",{className:"nhrrob-secure-header"},(0,n.createElement)("div",{className:"nhrrob-secure-header-main"},(0,n.createElement)("h1",null,(0,l.__)("NHR Secure Settings","nhrrob-secure")),(0,n.createElement)(s.Button,{className:"nhrrob-secure-dark-mode-toggle",icon:e.nhrrob_secure_dark_mode?(0,n.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",width:"20",height:"20"},(0,n.createElement)("path",{d:"M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58a.996.996 0 00-1.41 0 .996.996 0 000 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41L5.99 4.58zm12.37 12.37a.996.996 0 00-1.41 0 .996.996 0 000 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41l-1.06-1.06zm1.06-10.96a.996.996 0 00-1.41-1.41l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06zM7.05 18.36a.996.996 0 00-1.41-1.41l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06z"})):(0,n.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",width:"20",height:"20"},(0,n.createElement)("path",{d:"M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z"})),onClick:async()=>{const r=!e.nhrrob_secure_dark_mode;f("nhrrob_secure_dark_mode",r);try{await o()({path:"/nhrrob-secure/v1/settings",method:"POST",data:{...e,nhrrob_secure_dark_mode:r}})}catch(e){console.error("Failed to save dark mode preference",e)}},label:(0,l.__)("Toggle Dark Mode","nhrrob-secure")})),(0,n.createElement)("p",{className:"nhrrob-secure-subtitle"},(0,l.__)("Configure security features for your WordPress site","nhrrob-secure"))),p&&(0,n.createElement)(s.Notice,{status:p.type,isDismissible:!0,onRemove:()=>E(null)},p.message),(0,n.createElement)("div",{className:"nhrrob-secure-cards"},(0,n.createElement)(i,{settings:e,updateSetting:f}),(0,n.createElement)(u,{settings:e,updateSetting:f}),(0,n.createElement)(m,{settings:e,updateSetting:f}),(0,n.createElement)(h,{settings:e,updateSetting:f}),(0,n.createElement)(b,null),(0,n.createElement)(_,null)),(0,n.createElement)("div",{className:"nhrrob-secure-actions"},(0,n.createElement)(s.Button,{variant:"primary",onClick:async()=>{g(!0),E(null);try{await o()({path:"/nhrrob-secure/v1/settings",method:"POST",data:e}),E({type:"success",message:(0,l.__)("Settings saved successfully!","nhrrob-secure")})}catch(e){E({type:"error",message:(0,l.__)("Failed to save settings","nhrrob-secure")})}finally{g(!1)}},isBusy:d,disabled:d},d?(0,l.__)("Saving...","nhrrob-secure"):(0,l.__)("Save Settings","nhrrob-secure"))))},null),g)}},t={};function n(e){var a=t[e];if(void 0!==a)return a.exports;var s=t[e]={exports:{}};return r[e](s,s.exports,n),s.exports}n.m=r,e=[],n.O=(r,t,a,s)=>{if(!t){var l=1/0;for(u=0;u<e.length;u++){for(var[t,a,s]=e[u],c=!0,o=0;o<t.length;o++)(!1&s||l>=s)&&Object.keys(n.O).every(e=>n.O[e](t[o]))?t.splice(o--,1):(c=!1,s<l&&(l=s));if(c){e.splice(u--,1);var i=a();void 0!==i&&(r=i)}}return r}s=s||0;for(var u=e.length;u>0&&e[u-1][2]>s;u--)e[u]=e[u-1];e[u]=[t,a,s]},n.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return n.d(r,{a:r}),r},n.d=(e,r)=>{for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),(()=>{var e={884:0,15:0};n.O.j=r=>0===e[r];var r=(r,t)=>{var a,s,[l,c,o]=t,i=0;if(l.some(r=>0!==e[r])){for(a in c)n.o(c,a)&&(n.m[a]=c[a]);if(o)var u=o(n)}for(r&&r(t);i<l.length;i++)s=l[i],n.o(e,s)&&e[s]&&e[s][0](),e[s]=0;return n.O(u)},t=globalThis.webpackChunknhrrob_secure=globalThis.webpackChunknhrrob_secure||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})();var a=n.O(void 0,[15],()=>n(967));a=n.O(a)})();1 (()=>{"use strict";var e,r={195(e,r,t){const n=window.React,s=window.wp.element,a=window.wp.components,l=window.wp.i18n,c=window.wp.apiFetch;var o=t.n(c);const i=({settings:e,updateSetting:r})=>(0,n.createElement)(a.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Login Protection","nhrrob-secure")),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Enable Login Attempts Limit","nhrrob-secure"),help:(0,l.__)("Limit failed login attempts to prevent brute force attacks","nhrrob-secure"),checked:e.nhrrob_secure_limit_login_attempts,onChange:e=>r("nhrrob_secure_limit_login_attempts",e)}),e.nhrrob_secure_limit_login_attempts&&(0,n.createElement)(a.TextControl,{label:(0,l.__)("Maximum Login Attempts","nhrrob-secure"),help:(0,l.__)("Number of failed attempts before blocking (default: 5)","nhrrob-secure"),type:"number",value:e.nhrrob_secure_login_attempts_limit,onChange:e=>r("nhrrob_secure_login_attempts_limit",parseInt(e)||5),min:"1",max:"20"}),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Enable Proxy IP Detection","nhrrob-secure"),help:(0,l.__)("Detect real IP behind proxies (Cloudflare, etc.)","nhrrob-secure"),checked:e.nhrrob_secure_enable_proxy_ip,onChange:e=>r("nhrrob_secure_enable_proxy_ip",e)}))),u=({settings:e,updateSetting:r})=>(0,n.createElement)(a.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Custom Login Page","nhrrob-secure")),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Enable Custom Login URL","nhrrob-secure"),help:(0,l.__)("Hide wp-login.php and use a custom login URL","nhrrob-secure"),checked:e.nhrrob_secure_custom_login_page,onChange:e=>r("nhrrob_secure_custom_login_page",e)}),e.nhrrob_secure_custom_login_page&&(0,n.createElement)(a.TextControl,{label:(0,l.__)("Custom Login URL","nhrrob-secure"),help:(0,l.__)("Your login page will be accessible at this URL","nhrrob-secure"),value:e.nhrrob_secure_custom_login_url,onChange:e=>r("nhrrob_secure_custom_login_url",e),placeholder:"/hidden-access-52w"}),e.nhrrob_secure_custom_login_page&&(0,n.createElement)("div",{className:"nhrrob-secure-info"},(0,n.createElement)("strong",null,(0,l.__)("Your login URL:","nhrrob-secure")),(0,n.createElement)("code",null,window.location.origin,e.nhrrob_secure_custom_login_url)))),m=({settings:e,updateSetting:r})=>{const t=e.nhrrob_secure_2fa_enforced_roles||[],s=e.available_roles||[];return(0,n.createElement)(a.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Two-Factor Authentication","nhrrob-secure")),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Enable Global 2FA","nhrrob-secure"),help:(0,n.createElement)(n.Fragment,null,(0,l.__)("Enables Google Authenticator support for all users. Users can set it up in their ","nhrrob-secure"),(0,n.createElement)("a",{href:nhrrobSecureSettings.profile_url,target:"_blank",rel:"noreferrer"},(0,l.__)("profile page","nhrrob-secure")),"."),checked:e.nhrrob_secure_enable_2fa,onChange:e=>r("nhrrob_secure_enable_2fa",e)}),e.nhrrob_secure_enable_2fa&&(0,n.createElement)(n.Fragment,null,(0,n.createElement)("div",{className:"nhrrob-secure-2fa-method pt-4 border-t border-gray-100"},(0,n.createElement)("h3",{className:"text-sm font-semibold mb-3"},(0,l.__)("2FA Method","nhrrob-secure")),(0,n.createElement)(a.RadioControl,{selected:e.nhrrob_secure_2fa_type||"app",options:[{label:(0,l.__)("Authenticator App (Recommended)","nhrrob-secure"),value:"app"},{label:(0,l.__)("Email OTP","nhrrob-secure"),value:"email"}],onChange:e=>r("nhrrob_secure_2fa_type",e)})),(0,n.createElement)("div",{className:"nhrrob-secure-enforced-roles pt-4 border-t border-gray-100"},(0,n.createElement)("h3",{className:"text-sm font-semibold mb-3"},(0,l.__)("Enforced 2FA by Role","nhrrob-secure")),(0,n.createElement)("p",{className:"text-xs text-gray-500 mb-4"},(0,l.__)("Users with the selected roles will be forced to set up 2FA before they can access the admin dashboard.","nhrrob-secure")),(0,n.createElement)("div",{className:"grid grid-cols-2 gap-2"},s.map(e=>(0,n.createElement)(a.CheckboxControl,{key:e.value,label:e.label,checked:t.includes(e.value),onChange:n=>((e,n)=>{const s=n?[...t,e]:t.filter(r=>r!==e);r("nhrrob_secure_2fa_enforced_roles",s)})(e.value,n)})))))))},h=({settings:e,updateSetting:r})=>(0,n.createElement)(a.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("File Protection","nhrrob-secure")),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Protect Debug Log","nhrrob-secure"),help:(0,l.__)("Block direct access to wp-content/debug.log","nhrrob-secure"),checked:e.nhrrob_secure_protect_debug_log,onChange:e=>r("nhrrob_secure_protect_debug_log",e)}))),d=window.wp.htmlEntities,b=()=>{const[e,r]=(0,s.useState)(null),[t,c]=(0,s.useState)(!0),[i,u]=(0,s.useState)(!1),[m,h]=(0,s.useState)(null);(0,s.useEffect)(()=>{b()},[]);const b=async()=>{try{const e=await o()({path:"/nhrrob-secure/v1/vulnerability/status"});r(e),c(!1)}catch(e){h((0,l.__)("Failed to fetch vulnerability status","nhrrob-secure")),c(!1)}};if(t)return(0,n.createElement)(a.Card,{className:"nhrrob-secure-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)(a.Spinner,null)));const _=e&&(e.core.length>0||e.plugins.length>0||e.themes.length>0);return(0,n.createElement)(a.Card,{className:"nhrrob-secure-card nhrrob-secure-vulnerability-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Vulnerability Checker","nhrrob-secure")),(0,n.createElement)(a.Button,{variant:"primary",onClick:async()=>{u(!0),h(null);try{const e=await o()({path:"/nhrrob-secure/v1/vulnerability/scan",method:"POST"});r(e)}catch(e){h((0,l.__)("Failed to run vulnerability scan","nhrrob-secure"))}finally{u(!1)}},isBusy:i,disabled:i,icon:"update",iconPosition:"right"},i?(0,l.__)("Scanning...","nhrrob-secure"):(0,l.__)("Scan Now","nhrrob-secure"))),(0,n.createElement)("p",{className:"nhrrob-secure-last-scan"},(0,n.createElement)("strong",null,(0,l.__)("Last Scan:","nhrrob-secure"))," ",(g=e.last_scan)?new Date(1e3*g).toLocaleString():(0,l.__)("Never","nhrrob-secure")),m&&(0,n.createElement)(a.Notice,{status:"error",isDismissible:!1},m),_?(0,n.createElement)("div",{className:"nhrrob-secure-vulnerability-list"},(0,n.createElement)(a.Notice,{status:"warning",isDismissible:!1},(0,l.__)("Vulnerabilities detected! Please review and update the items below.","nhrrob-secure")),e.core.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("WordPress Core","nhrrob-secure")),(0,n.createElement)("ul",null,e.core.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name))))),e.plugins.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("Plugins","nhrrob-secure")),e.plugins.map((e,r)=>(0,n.createElement)("div",{key:r,className:"vulnerability-item"},(0,n.createElement)("strong",null,(0,n.createElement)("a",{href:"plugins.php",style:{textDecoration:"none",color:"inherit"}},(0,d.decodeEntities)(e.name)),(0,n.createElement)("span",{style:{fontWeight:"normal",color:"#666"}}," (",e.version,")")),(0,n.createElement)("ul",null,e.vulnerabilities.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name))))))),e.themes.length>0&&(0,n.createElement)("div",{className:"vulnerability-section"},(0,n.createElement)("h3",null,(0,l.__)("Themes","nhrrob-secure")),e.themes.map((e,r)=>(0,n.createElement)("div",{key:r,className:"vulnerability-item"},(0,n.createElement)("strong",null,(0,d.decodeEntities)(e.name)," (",e.version,")"),(0,n.createElement)("ul",null,e.vulnerabilities.map((e,r)=>(0,n.createElement)("li",{key:r},(0,d.decodeEntities)(e.name)))))))):(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No known vulnerabilities detected.","nhrrob-secure"))));var g},_=()=>{const[e,r]=(0,s.useState)(!1),[t,c]=(0,s.useState)(null),[i,u]=(0,s.useState)(null),[m,h]=(0,s.useState)("core"),d=async()=>{r(!0),u(null),c(null);try{const e="core"===m?"/nhrrob-secure/v1/scanner/core":"/nhrrob-secure/v1/scanner/malware",r=await o()({path:e,method:"POST"});c(r)}catch(e){u(e.message||(0,l.__)("An error occurred during scan.","nhrrob-secure"))}finally{r(!1)}};return(0,n.createElement)("div",{className:"nhrrob-secure-card nhrrob-secure-vulnerability-card padded-header"},(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("div",{className:"nhrrob-secure-header-content"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("File Scanner","nhrrob-secure")),(0,n.createElement)("p",{className:"nhrrob-secure-card-subtitle"},(0,l.__)("Scan your site for file modifications and potential malware.","nhrrob-secure"))),(0,n.createElement)("div",{className:"nhrrob-scan-controls"},(0,n.createElement)("div",{className:"nhrrob-scan-type-toggle"},(0,n.createElement)("button",{className:"nhrrob-scan-toggle-btn "+("core"===m?"active":""),onClick:()=>h("core"),disabled:e},(0,l.__)("Core Integrity","nhrrob-secure")),(0,n.createElement)("button",{className:"nhrrob-scan-toggle-btn "+("malware"===m?"active":""),onClick:()=>h("malware"),disabled:e},(0,l.__)("Malware Scan","nhrrob-secure"))),(0,n.createElement)(a.Button,{variant:"primary",onClick:()=>d(),isBusy:e,disabled:e,icon:"update",iconPosition:"right"},e?(0,l.__)("Scanning...","nhrrob-secure"):(0,l.__)("Start Scan","nhrrob-secure")))),(0,n.createElement)("div",{className:"nhrrob-card-body"},i&&(0,n.createElement)("div",{className:"notice notice-error inline-notice"},(0,n.createElement)("p",null,i)),t&&(0,n.createElement)("div",{className:"nhrrob-secure-vulnerability-list"},("core"===m&&(t.modified?.length>0||t.missing?.length>0)||"malware"===m&&t.suspicious?.length>0)&&(0,n.createElement)("div",{className:"notice notice-warning inline-notice nhrrob-warning-notice"},(0,n.createElement)("p",null,(0,l.__)("Issues detected! Please review and update the items below.","nhrrob-secure"))),"core"===m&&(0,n.createElement)(n.Fragment,null,t.modified&&t.modified.length>0&&(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Modified Core Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.modified.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e)),(0,n.createElement)(a.Button,{variant:"secondary",isSmall:!0,onClick:()=>(async e=>{if(confirm((0,l.__)("Are you sure you want to repair this file? It will be overwritten with the original version.","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/scanner/repair",method:"POST",data:{file:e}}),alert((0,l.__)("File repaired successfully.","nhrrob-secure")),d()}catch(e){alert(e.message||(0,l.__)("Repair failed.","nhrrob-secure"))}})(e)},(0,l.__)("Repair","nhrrob-secure")))))),t.missing&&t.missing.length>0&&(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Missing Core Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.missing.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e)))))),!t.modified?.length&&!t.missing?.length&&(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No modified core files found.","nhrrob-secure"))),"malware"===m&&(0,n.createElement)(n.Fragment,null,t.suspicious&&t.suspicious.length>0?(0,n.createElement)("div",{className:"nhrrob-result-group"},(0,n.createElement)("h3",{className:"nhrrob-result-group-title"},(0,l.__)("Suspicious Files","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-result-list"},t.suspicious.map((e,r)=>(0,n.createElement)("div",{key:r,className:"nhrrob-result-row"},(0,n.createElement)("div",{className:"nhrrob-file-info"},(0,n.createElement)("strong",null,e.file),(0,n.createElement)("span",{className:"nhrrob-file-meta"},e.reason)),(0,n.createElement)(a.Button,{variant:"link",isDestructive:!0,onClick:()=>(async e=>{if(confirm((0,l.__)("Are you sure you want to PERMANENTLY delete this file?","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/scanner/delete",method:"POST",data:{file:e}}),alert((0,l.__)("File deleted successfully.","nhrrob-secure")),d()}catch(e){alert(e.message||(0,l.__)("Delete failed.","nhrrob-secure"))}})(e.file)},(0,l.__)("Delete","nhrrob-secure")))))):(0,n.createElement)("div",{className:"nhrrob-secure-status-success"},(0,n.createElement)("span",{className:"dashicons dashicons-yes-alt"}),(0,l.__)("No suspicious files found.","nhrrob-secure")),(0,n.createElement)("p",{className:"description nhrrob-scan-count"},(0,n.createElement)("small",null,(0,l.__)("Scanned files:","nhrrob-secure")," ",t.scanned_count))))))},g=({settings:e,updateSetting:r})=>(0,n.createElement)(a.Card,{className:"nhrrob-secure-card nhrrob-secure-hardening-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Hardening & Firewall","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-secure-setting-group"},(0,n.createElement)("h3",{className:"nhrrob-secure-setting-subtitle"},(0,l.__)("General Hardening","nhrrob-secure")),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Disable XML-RPC","nhrrob-secure"),help:(0,l.__)("Prevents external systems (like mobile apps and Jetpack) from accessing your site via XML-RPC. Recommended if not used.","nhrrob-secure"),checked:e.nhrrob_secure_disable_xmlrpc,onChange:e=>r("nhrrob_secure_disable_xmlrpc",e)}),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Disable File Editor","nhrrob-secure"),help:(0,l.__)("Disables the built-in theme and plugin file editor to prevent code execution if an admin account is compromised.","nhrrob-secure"),checked:e.nhrrob_secure_disable_file_editor,onChange:e=>r("nhrrob_secure_disable_file_editor",e)}),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Hide WP Version","nhrrob-secure"),help:(0,l.__)("Removes WordPress version from page source and RSS feeds to make reconnaissance harder for attackers.","nhrrob-secure"),checked:e.nhrrob_secure_hide_wp_version,onChange:e=>r("nhrrob_secure_hide_wp_version",e)}),(0,n.createElement)(a.ToggleControl,{label:(0,l.__)("Disable REST API User Enumeration","nhrrob-secure"),help:(0,l.__)("Blocks access to /wp-json/wp/v2/users to prevent attackers from listing your users.","nhrrob-secure"),checked:e.nhrrob_secure_disable_rest_users,onChange:e=>r("nhrrob_secure_disable_rest_users",e)})),(0,n.createElement)("div",{className:"nhrrob-secure-setting-group border-t border-gray-100 pt-4 mt-4"},(0,n.createElement)("h3",{className:"nhrrob-secure-setting-subtitle"},(0,l.__)("Firewall Rules","nhrrob-secure")),(0,n.createElement)(a.TextareaControl,{label:(0,l.__)("Block User Agents","nhrrob-secure"),help:(0,l.__)('Enter one User-Agent per line to block. Case-insensitive partial match. Example: "HTTrack", "curl".',"nhrrob-secure"),value:e.nhrrob_secure_firewall_blocked_uas,onChange:e=>r("nhrrob_secure_firewall_blocked_uas",e),rows:5,placeholder:"SemrushBot\nAhrefsBot\nMJ12bot"})))),E=({settings:e,updateSetting:r})=>{const[t,c]=(0,s.useState)([]),[i,u]=(0,s.useState)(!1),[m,h]=(0,s.useState)(null);(0,s.useEffect)(()=>{d()},[]);const d=async()=>{u(!0),h(null);try{const e=await o()({path:"/nhrrob-secure/v1/sessions"});c(e)}catch(e){h(e.message||(0,l.__)("Failed to load sessions.","nhrrob-secure"))}finally{u(!1)}};return(0,n.createElement)(a.Card,{className:"nhrrob-secure-card nhrrob-secure-sessions-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("User Session Management","nhrrob-secure")),(0,n.createElement)(a.Button,{variant:"primary",onClick:d,isBusy:i,disabled:i,icon:"update"},(0,l.__)("Refresh","nhrrob-secure"))),(0,n.createElement)("div",{className:"nhrrob-secure-setting-group"},(0,n.createElement)(a.TextControl,{label:(0,l.__)("Idle Timeout (Minutes)","nhrrob-secure"),help:(0,l.__)("Automatically log out inactive users after X minutes. Set to 0 to disable.","nhrrob-secure"),type:"number",value:e?.nhrrob_secure_idle_timeout||0,onChange:e=>r("nhrrob_secure_idle_timeout",parseInt(e)||0),min:"0"})),m&&(0,n.createElement)(a.Notice,{status:"error",isDismissible:!1},m),(0,n.createElement)("div",{className:"nhrrob-secure-sessions-list mt-4"},(0,n.createElement)("h3",{className:"text-sm font-semibold mb-3"},(0,l.__)("Active Sessions","nhrrob-secure")),0!==t.length||i?(0,n.createElement)("div",{className:"sessions-grid"},t.map((e,r)=>(0,n.createElement)("div",{key:r,className:"session-item p-3 border rounded mb-2 "+(e.is_current?"bg-blue-50 border-blue-200":"bg-gray-50 border-gray-200")},(0,n.createElement)("div",{className:"flex justify-between items-start"},(0,n.createElement)("div",{className:"session-info"},(0,n.createElement)("div",{className:"font-medium text-gray-700"},e.ip,e.is_current&&(0,n.createElement)("span",{className:"ml-2 px-2 py-0.5 text-xs bg-blue-100 text-blue-800 rounded-full"},(0,l.__)("Current Session","nhrrob-secure"))),(0,n.createElement)("div",{className:"text-xs text-gray-500 mt-1"},(0,n.createElement)("div",null,(0,l.__)("Login:","nhrrob-secure")," ",new Date(1e3*e.login).toLocaleString()),(0,n.createElement)("div",null,(0,l.__)("Expires:","nhrrob-secure")," ",new Date(1e3*e.expiration).toLocaleString()),(0,n.createElement)("div",{className:"mt-1 font-mono text-gray-400 truncate w-64",title:e.ua},e.ua))),!e.is_current&&(0,n.createElement)(a.Button,{variant:"link",isDestructive:!0,onClick:()=>(async e=>{if(confirm((0,l.__)("Are you sure you want to log out this session?","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/sessions/destroy",method:"POST",data:{verifier:e}}),d()}catch(e){alert(e.message||(0,l.__)("Failed to destroy session.","nhrrob-secure"))}})(e.verifier)},(0,l.__)("Logout","nhrrob-secure")))))):(0,n.createElement)("p",null,(0,l.__)("No active sessions found.","nhrrob-secure"))),t.length>1&&(0,n.createElement)("div",{className:"mt-4 pt-3 border-t"},(0,n.createElement)(a.Button,{variant:"secondary",isDestructive:!0,onClick:async()=>{if(confirm((0,l.__)("Are you sure you want to log out all other devices?","nhrrob-secure")))try{await o()({path:"/nhrrob-secure/v1/sessions/destroy-others",method:"POST"}),d(),alert((0,l.__)("All other sessions logged out.","nhrrob-secure"))}catch(e){alert(e.message||(0,l.__)("Failed to destroy sessions.","nhrrob-secure"))}},className:"w-full justify-center"},(0,l.__)("Log Out All Other Devices","nhrrob-secure")))))},p=({settings:e,updateSetting:r})=>{const[t,c]=(0,s.useState)([]),[i,u]=(0,s.useState)(!0),[m,h]=(0,s.useState)(0),[d,b]=(0,s.useState)(1);(0,s.useEffect)(()=>{_()},[d]);const _=async()=>{u(!0);try{const e=20*(d-1),r=await o()({path:`/nhrrob-secure/v1/logs?limit=20&offset=${e}`});c(r.items),h(r.total)}catch(e){console.error(e)}finally{u(!1)}},g=Math.ceil(m/20);return(0,n.createElement)(a.Card,{className:"nhrrob-secure-card nhrrob-secure-audit-log-card"},(0,n.createElement)(a.CardBody,null,(0,n.createElement)("div",{className:"nhrrob-secure-card-header-flex"},(0,n.createElement)("h2",{className:"nhrrob-secure-card-title"},(0,l.__)("Activity Audit Log","nhrrob-secure")),(0,n.createElement)("div",{className:"nhrrob-secure-card-header-actions"},e&&(0,n.createElement)(a.SelectControl,{className:"nhrrob-secure-retention-select",value:e.nhrrob_secure_log_retention_days,options:[{label:(0,l.__)("Keep logs: 7 days","nhrrob-secure"),value:7},{label:(0,l.__)("Keep logs: 30 days","nhrrob-secure"),value:30},{label:(0,l.__)("Keep logs: 90 days","nhrrob-secure"),value:90},{label:(0,l.__)("Keep logs: 1 year","nhrrob-secure"),value:365}],onChange:e=>r("nhrrob_secure_log_retention_days",parseInt(e))}),(0,n.createElement)(a.Button,{variant:"primary",onClick:_,disabled:i,isBusy:i,icon:"update",iconPosition:"right"},(0,l.__)("Refresh","nhrrob-secure")))),i&&(0,n.createElement)("div",{className:"nhrrob-secure-loading-overlay"},(0,n.createElement)(a.Spinner,null)),(0,n.createElement)("div",{className:"nhrrob-secure-audit-table-wrapper"},(0,n.createElement)("table",{className:"nhrrob-secure-audit-table"},(0,n.createElement)("thead",null,(0,n.createElement)("tr",null,(0,n.createElement)("th",null,(0,l.__)("Date","nhrrob-secure")),(0,n.createElement)("th",null,(0,l.__)("User","nhrrob-secure")),(0,n.createElement)("th",null,(0,l.__)("Context","nhrrob-secure")),(0,n.createElement)("th",null,(0,l.__)("Action","nhrrob-secure")),(0,n.createElement)("th",null,(0,l.__)("Item","nhrrob-secure")),(0,n.createElement)("th",null,(0,l.__)("IP Address","nhrrob-secure")))),(0,n.createElement)("tbody",null,t.length>0?t.map(e=>(0,n.createElement)("tr",{key:e.id,className:`severity-${e.severity}`},(0,n.createElement)("td",null,new Date(e.date).toLocaleString()),(0,n.createElement)("td",null,e.user),(0,n.createElement)("td",null,(0,n.createElement)("span",{className:"nhrrob-secure-badge"},e.context)),(0,n.createElement)("td",null,e.action),(0,n.createElement)("td",null,e.label),(0,n.createElement)("td",null,e.ip))):(0,n.createElement)("tr",null,(0,n.createElement)("td",{colSpan:"6",className:"no-logs"},!i&&(0,l.__)("No activity logs found.","nhrrob-secure")))))),g>1&&(0,n.createElement)("div",{className:"nhrrob-secure-pagination"},(0,n.createElement)(a.Button,{isSmall:!0,disabled:1===d||i,onClick:()=>b(d-1)},"« ",(0,l.__)("Prev","nhrrob-secure")),(0,n.createElement)("span",{className:"nhrrob-secure-page-info"},(0,l.__)("Page","nhrrob-secure")," ",d," ",(0,l.__)("of","nhrrob-secure")," ",g),(0,n.createElement)(a.Button,{isSmall:!0,disabled:d===g||i,onClick:()=>b(d+1)},(0,l.__)("Next","nhrrob-secure")," »"))))},v=document.getElementById("nhrrob-secure-settings-root");v&&(0,s.render)((0,n.createElement)(()=>{const[e,r]=(0,s.useState)(null),[t,c]=(0,s.useState)(!0),[d,v]=(0,s.useState)(!1),[y,f]=(0,s.useState)(null);(0,s.useEffect)(()=>{N()},[]);const N=async()=>{try{const e=await o()({path:"/nhrrob-secure/v1/settings"});r(e),c(!1)}catch(e){f({type:"error",message:(0,l.__)("Failed to load settings","nhrrob-secure")}),c(!1)}},w=(t,n)=>{r({...e,[t]:n})};return(0,s.useEffect)(()=>{e?.nhrrob_secure_dark_mode?document.body.classList.add("nhrrob-secure-dark-mode-active"):document.body.classList.remove("nhrrob-secure-dark-mode-active")},[e?.nhrrob_secure_dark_mode]),t?(0,n.createElement)("div",{className:"nhrrob-secure-loading"},(0,n.createElement)(a.Spinner,null)):(0,n.createElement)("div",{className:"nhrrob-secure-settings "+(e.nhrrob_secure_dark_mode?"dark-mode":"")},(0,n.createElement)("div",{className:"nhrrob-secure-header"},(0,n.createElement)("div",{className:"nhrrob-secure-header-main"},(0,n.createElement)("h1",null,(0,l.__)("NHR Secure Settings","nhrrob-secure")),(0,n.createElement)(a.Button,{className:"nhrrob-secure-dark-mode-toggle",icon:e.nhrrob_secure_dark_mode?(0,n.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",width:"20",height:"20"},(0,n.createElement)("path",{d:"M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58a.996.996 0 00-1.41 0 .996.996 0 000 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41L5.99 4.58zm12.37 12.37a.996.996 0 00-1.41 0 .996.996 0 000 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41l-1.06-1.06zm1.06-10.96a.996.996 0 00-1.41-1.41l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06zM7.05 18.36a.996.996 0 00-1.41-1.41l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06z"})):(0,n.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",width:"20",height:"20"},(0,n.createElement)("path",{d:"M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z"})),onClick:async()=>{const r=!e.nhrrob_secure_dark_mode;w("nhrrob_secure_dark_mode",r);try{await o()({path:"/nhrrob-secure/v1/settings",method:"POST",data:{...e,nhrrob_secure_dark_mode:r}})}catch(e){console.error("Failed to save dark mode preference",e)}},label:(0,l.__)("Toggle Dark Mode","nhrrob-secure")})),(0,n.createElement)("p",{className:"nhrrob-secure-subtitle"},(0,l.__)("Configure security features for your WordPress site","nhrrob-secure"))),y&&(0,n.createElement)(a.Notice,{status:y.type,isDismissible:!0,onRemove:()=>f(null)},y.message),(0,n.createElement)("div",{className:"nhrrob-secure-cards"},(0,n.createElement)(i,{settings:e,updateSetting:w}),(0,n.createElement)(u,{settings:e,updateSetting:w}),(0,n.createElement)(m,{settings:e,updateSetting:w}),(0,n.createElement)(g,{settings:e,updateSetting:w}),(0,n.createElement)(h,{settings:e,updateSetting:w}),(0,n.createElement)(b,null),(0,n.createElement)(_,null),(0,n.createElement)(E,{settings:e,updateSetting:w}),(0,n.createElement)(p,{settings:e,updateSetting:w})),(0,n.createElement)("div",{className:"nhrrob-secure-actions"},(0,n.createElement)(a.Button,{variant:"primary",onClick:async()=>{v(!0),f(null);try{await o()({path:"/nhrrob-secure/v1/settings",method:"POST",data:e}),f({type:"success",message:(0,l.__)("Settings saved successfully!","nhrrob-secure")})}catch(e){f({type:"error",message:(0,l.__)("Failed to save settings","nhrrob-secure")})}finally{v(!1)}},isBusy:d,disabled:d},d?(0,l.__)("Saving...","nhrrob-secure"):(0,l.__)("Save Settings","nhrrob-secure"))))},null),v)}},t={};function n(e){var s=t[e];if(void 0!==s)return s.exports;var a=t[e]={exports:{}};return r[e](a,a.exports,n),a.exports}n.m=r,e=[],n.O=(r,t,s,a)=>{if(!t){var l=1/0;for(u=0;u<e.length;u++){for(var[t,s,a]=e[u],c=!0,o=0;o<t.length;o++)(!1&a||l>=a)&&Object.keys(n.O).every(e=>n.O[e](t[o]))?t.splice(o--,1):(c=!1,a<l&&(l=a));if(c){e.splice(u--,1);var i=s();void 0!==i&&(r=i)}}return r}a=a||0;for(var u=e.length;u>0&&e[u-1][2]>a;u--)e[u]=e[u-1];e[u]=[t,s,a]},n.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return n.d(r,{a:r}),r},n.d=(e,r)=>{for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),(()=>{var e={884:0,15:0};n.O.j=r=>0===e[r];var r=(r,t)=>{var s,a,[l,c,o]=t,i=0;if(l.some(r=>0!==e[r])){for(s in c)n.o(c,s)&&(n.m[s]=c[s]);if(o)var u=o(n)}for(r&&r(t);i<l.length;i++)a=l[i],n.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return n.O(u)},t=globalThis.webpackChunknhrrob_secure=globalThis.webpackChunknhrrob_secure||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})();var s=n.O(void 0,[15],()=>n(195));s=n.O(s)})(); -
nhrrob-secure/trunk/build/profile.asset.php
r3436910 r3441244 1 <?php return array('dependencies' => array(), 'version' => ' 60edf98ad68210cc7955');1 <?php return array('dependencies' => array(), 'version' => 'b365bbc000a0d9a2f03a'); -
nhrrob-secure/trunk/build/profile.css
r3436910 r3441244 280 280 margin-bottom: 1rem 281 281 } 282 .ml-2 { 283 284 margin-left: 0.5rem 285 } 282 286 .ml-5 { 283 287 … … 288 292 margin-top: 0px 289 293 } 294 .mt-1 { 295 296 margin-top: 0.25rem 297 } 290 298 .mt-4 { 291 299 292 300 margin-top: 1rem 293 301 } 302 .block { 303 304 display: block 305 } 306 .flex { 307 308 display: flex 309 } 294 310 .table { 295 311 … … 304 320 display: none 305 321 } 322 .w-64 { 323 324 width: 16rem 325 } 326 .w-full { 327 328 width: 100% 329 } 306 330 .grid-cols-2 { 307 331 308 332 grid-template-columns: repeat(2, minmax(0, 1fr)) 309 333 } 334 .items-start { 335 336 align-items: flex-start 337 } 338 .justify-center { 339 340 justify-content: center 341 } 342 .justify-between { 343 344 justify-content: space-between 345 } 310 346 .gap-2 { 311 347 312 348 gap: 0.5rem 313 349 } 350 .truncate { 351 352 overflow: hidden; 353 354 text-overflow: ellipsis; 355 356 white-space: nowrap 357 } 358 .rounded { 359 360 border-radius: 0.25rem 361 } 362 .rounded-full { 363 364 border-radius: 9999px 365 } 366 .border { 367 368 border-width: 1px 369 } 314 370 .border-t { 315 371 316 372 border-top-width: 1px 317 373 } 374 .border-blue-200 { 375 376 --tw-border-opacity: 1; 377 378 border-color: rgb(191 219 254 / var(--tw-border-opacity, 1)) 379 } 318 380 .border-gray-100 { 319 381 … … 322 384 border-color: rgb(243 244 246 / var(--tw-border-opacity, 1)) 323 385 } 386 .border-gray-200 { 387 388 --tw-border-opacity: 1; 389 390 border-color: rgb(229 231 235 / var(--tw-border-opacity, 1)) 391 } 392 .bg-blue-100 { 393 394 --tw-bg-opacity: 1; 395 396 background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1)) 397 } 398 .bg-blue-50 { 399 400 --tw-bg-opacity: 1; 401 402 background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1)) 403 } 404 .bg-gray-50 { 405 406 --tw-bg-opacity: 1; 407 408 background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1)) 409 } 410 .p-3 { 411 412 padding: 0.75rem 413 } 414 .px-2 { 415 416 padding-left: 0.5rem; 417 418 padding-right: 0.5rem 419 } 420 .py-0\.5 { 421 422 padding-top: 0.125rem; 423 424 padding-bottom: 0.125rem 425 } 426 .pt-3 { 427 428 padding-top: 0.75rem 429 } 324 430 .pt-4 { 325 431 326 432 padding-top: 1rem 327 433 } 434 .font-mono { 435 436 font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace 437 } 328 438 .text-sm { 329 439 … … 338 448 line-height: 1rem 339 449 } 450 .font-medium { 451 452 font-weight: 500 453 } 340 454 .font-semibold { 341 455 342 456 font-weight: 600 343 457 } 458 .text-blue-800 { 459 460 --tw-text-opacity: 1; 461 462 color: rgb(30 64 175 / var(--tw-text-opacity, 1)) 463 } 464 .text-gray-400 { 465 466 --tw-text-opacity: 1; 467 468 color: rgb(156 163 175 / var(--tw-text-opacity, 1)) 469 } 344 470 .text-gray-500 { 345 471 … … 348 474 color: rgb(107 114 128 / var(--tw-text-opacity, 1)) 349 475 } 476 .text-gray-700 { 477 478 --tw-text-opacity: 1; 479 480 color: rgb(55 65 81 / var(--tw-text-opacity, 1)) 481 } 350 482 .filter { 351 483 -
nhrrob-secure/trunk/includes/Admin/Api.php
r3438122 r3441244 90 90 'sanitize_callback' => 'rest_sanitize_boolean', 91 91 ], 92 'nhrrob_secure_log_retention_days' => [ 93 'type' => 'integer', 94 'sanitize_callback' => 'absint', 95 ], 96 'nhrrob_secure_disable_xmlrpc' => [ 97 'type' => 'boolean', 98 'sanitize_callback' => 'rest_sanitize_boolean', 99 ], 100 'nhrrob_secure_disable_file_editor' => [ 101 'type' => 'boolean', 102 'sanitize_callback' => 'rest_sanitize_boolean', 103 ], 104 'nhrrob_secure_hide_wp_version' => [ 105 'type' => 'boolean', 106 'sanitize_callback' => 'rest_sanitize_boolean', 107 ], 108 'nhrrob_secure_disable_rest_users' => [ 109 'type' => 'boolean', 110 'sanitize_callback' => 'rest_sanitize_boolean', 111 ], 112 'nhrrob_secure_firewall_blocked_uas' => [ 113 'type' => 'string', 114 'sanitize_callback' => 'sanitize_textarea_field', 115 ], 116 'nhrrob_secure_idle_timeout' => [ 117 'type' => 'integer', 118 'sanitize_callback' => 'absint', 119 ], 92 120 ], 93 121 ]); … … 161 189 ]); 162 190 191 // Get audit logs 192 register_rest_route('nhrrob-secure/v1', '/logs', [ 193 'methods' => 'GET', 194 'callback' => [$this, 'get_logs'], 195 'permission_callback' => function () { 196 return current_user_can('manage_options'); 197 }, 198 ]); 199 200 // Get sessions 201 register_rest_route('nhrrob-secure/v1', '/sessions', [ 202 'methods' => 'GET', 203 'callback' => [$this, 'get_sessions_list'], 204 'permission_callback' => function () { 205 return current_user_can('manage_options'); 206 }, 207 ]); 208 209 // Destroy session 210 register_rest_route('nhrrob-secure/v1', '/sessions/destroy', [ 211 'methods' => 'POST', 212 'callback' => [$this, 'destroy_session'], 213 'permission_callback' => function () { 214 return current_user_can('manage_options'); 215 }, 216 'args' => [ 217 'verifier' => [ 218 'required' => true, 219 'type' => 'string', 220 'sanitize_callback' => 'sanitize_text_field', 221 ], 222 ], 223 ]); 224 225 // Destroy other sessions 226 register_rest_route('nhrrob-secure/v1', '/sessions/destroy-others', [ 227 'methods' => 'POST', 228 'callback' => [$this, 'destroy_other_sessions'], 229 'permission_callback' => function () { 230 return current_user_can('manage_options'); 231 }, 232 ]); 163 233 } 164 234 … … 179 249 'nhrrob_secure_2fa_type' => get_option('nhrrob_secure_2fa_type', 'app'), 180 250 'nhrrob_secure_dark_mode' => (bool) get_option('nhrrob_secure_dark_mode', false), 251 'nhrrob_secure_log_retention_days' => (int) get_option('nhrrob_secure_log_retention_days', 30), 252 'nhrrob_secure_disable_xmlrpc' => (bool) get_option('nhrrob_secure_disable_xmlrpc', false), 253 'nhrrob_secure_disable_file_editor' => (bool) get_option('nhrrob_secure_disable_file_editor', false), 254 'nhrrob_secure_hide_wp_version' => (bool) get_option('nhrrob_secure_hide_wp_version', false), 255 'nhrrob_secure_disable_rest_users' => (bool) get_option('nhrrob_secure_disable_rest_users', false), 256 'nhrrob_secure_firewall_blocked_uas' => get_option('nhrrob_secure_firewall_blocked_uas', ''), 257 'nhrrob_secure_idle_timeout' => (int) get_option('nhrrob_secure_idle_timeout', 0), 181 258 'available_roles' => $this->get_available_roles(), 182 259 ]; … … 268 345 $scanner = new \NHRRob\Secure\FileScanner(); 269 346 $result = $scanner->repair_core_file($file); 270 347 271 348 if (is_wp_error($result)) { 272 349 return $result; 273 350 } 274 351 275 352 return ['success' => true, 'message' => 'File repaired successfully.']; 276 353 } … … 283 360 $file = $request->get_param('file'); 284 361 $scanner = new \NHRRob\Secure\FileScanner(); 285 362 286 363 // Security check: ensure file is inside WP_CONTENT_DIR 287 364 if (strpos($file, WP_CONTENT_DIR) !== 0) { … … 290 367 291 368 if ($scanner->delete_file($file)) { 292 return ['success' => true, 'message' => 'File deleted successfully.'];293 } 294 369 return ['success' => true, 'message' => 'File deleted successfully.']; 370 } 371 295 372 return new \WP_Error('delete_failed', 'Could not delete file.'); 296 373 } 374 375 /** 376 * Get audit logs 377 */ 378 public function get_logs($request) 379 { 380 $limit = $request->get_param('limit') ? (int) $request->get_param('limit') : 20; 381 $offset = $request->get_param('offset') ? (int) $request->get_param('offset') : 0; 382 383 $audit_log = new \NHRRob\Secure\AuditLog(); 384 return $audit_log->get_logs($limit, $offset); 385 } 386 /** 387 * Get sessions list 388 */ 389 public function get_sessions_list() 390 { 391 $manager = new \NHRRob\Secure\SessionManager(); 392 $sessions = $manager->get_sessions(get_current_user_id()); 393 $current_token = wp_get_session_token(); 394 395 $formatted = []; 396 foreach ($sessions as $verifier => $session) { 397 $formatted[] = [ 398 'verifier' => $verifier, 399 'ip' => $session['ip'], 400 'ua' => $session['ua'], 401 'login' => $session['login'], 402 'expiration' => $session['expiration'], 403 'is_current' => $verifier === $current_token, 404 ]; 405 } 406 407 return $formatted; 408 } 409 410 /** 411 * Destroy session 412 */ 413 public function destroy_session($request) 414 { 415 $verifier = $request->get_param('verifier'); 416 $manager = new \NHRRob\Secure\SessionManager(); 417 $manager->destroy_session(get_current_user_id(), $verifier); 418 419 return ['success' => true]; 420 } 421 422 /** 423 * Destroy other sessions 424 */ 425 public function destroy_other_sessions() 426 { 427 $manager = new \NHRRob\Secure\SessionManager(); 428 $manager->destroy_other_sessions(get_current_user_id()); 429 430 return ['success' => true]; 431 } 297 432 } -
nhrrob-secure/trunk/includes/App.php
r3435758 r3441244 6 6 * App base class 7 7 */ 8 class App { 8 class App 9 { 10 /** 11 * Initialize the class 12 */ 13 public function __construct() 14 { 15 // Base init 16 } 17 9 18 /** 10 19 * Render a template … … 13 22 * @param array $args 14 23 */ 15 public function render( $name, $args = [] ) { 16 extract( $args ); 24 public function render($name, $args = []) 25 { 26 extract($args); 17 27 $template = NHRROB_SECURE_PATH . '/templates/' . $name . '.php'; 18 28 19 if ( file_exists( $template )) {29 if (file_exists($template)) { 20 30 include $template; 21 31 } -
nhrrob-secure/trunk/nhrrob-secure.php
r3438122 r3441244 1 1 <?php 2 2 /** 3 * Plugin Name: NHR Secure – Hide Admin, Limit Login, 2FA & Vulnerability Checker3 * Plugin Name: NHR Secure – Login Security, Firewall, 2FA & Audit Log 4 4 * Plugin URI: http://wordpress.org/plugins/nhrrob-secure/ 5 5 * Description: Lightweight WordPress security plugin that protects your admin area, hides debug logs, limits login attempts, and checks for vulnerabilities. Minimal code, maximum protection. 6 6 * Author: Nazmul Hasan Robin 7 7 * Author URI: https://profiles.wordpress.org/nhrrob/ 8 * Version: 1. 1.08 * Version: 1.2.0 9 9 * Requires at least: 6.0 10 10 * Requires PHP: 7.4 … … 31 31 * @var string 32 32 */ 33 const version = '1. 1.0';33 const version = '1.2.0'; 34 34 35 35 /** … … 103 103 new \NHRRob\Secure\FileScanner(); 104 104 105 // Initialize hardening and firewall 106 new \NHRRob\Secure\Hardening(); 107 108 // Initialize session manager 109 new \NHRRob\Secure\SessionManager(); 110 111 // Initialize audit log 112 new \NHRRob\Secure\AuditLog(); 113 105 114 // Initialize admin menu 106 115 if (is_admin()) { … … 119 128 wp_schedule_event(time(), 'daily', 'nhrrob_secure_vulnerability_scan_cron'); 120 129 } 130 131 if (!wp_next_scheduled('nhrrob_secure_daily_cleanup')) { 132 wp_schedule_event(time(), 'daily', 'nhrrob_secure_daily_cleanup'); 133 } 134 135 // Create audit log table 136 (new \NHRRob\Secure\AuditLog())->maybe_install_schema(); 121 137 } 122 138 … … 129 145 { 130 146 wp_clear_scheduled_hook('nhrrob_secure_vulnerability_scan_cron'); 147 wp_clear_scheduled_hook('nhrrob_secure_daily_cleanup'); 131 148 } 132 149 } -
nhrrob-secure/trunk/readme.txt
r3438122 r3441244 1 === NHR Secure – Hide Admin, Limit Login, 2FA & Vulnerability Checker===1 === NHR Secure – Login Security, Firewall, 2FA & Audit Log === 2 2 Contributors: nhrrob 3 3 Tags: security, hide admin, login protection, debug log, 2fa … … 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 1. 1.07 Stable tag: 1.2.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 56 56 - Check file integrity 57 57 58 ### 🖥️ User Session Management 59 Monitor and control active user sessions to prevent unauthorized access. 60 - **View Active Sessions:** See IP, location, device, and login time for all logged-in users. 61 - **Remote Logout:** Instantly log out suspicious sessions or all other devices. 62 - **Idle Timeout:** Automatically log out inactive users after a set period. 63 64 ### 🧱 Hardening & Firewall 65 Essential security hardening to lock down your WordPress site. 66 - **Disable XML-RPC:** Prevent remote attacks and brute-force attempts. 67 - **Disable File Editor:** Stop file modifications from the dashboard. 68 - **Hide WP Version:** Obscure your WordPress version from attackers. 69 - **Block User-Agents:** Prevent bad bots and scrapers from accessing your site. 70 - **Disable User Enumeration:** Stop attackers from harvesting usernames via REST API. 71 72 ### 📝 Activity Audit Log 73 Keep a record of important security events on your site. 74 - Tracks logins, failed attempts, file changes, and settings updates. 75 - View user, IP, and event details. 76 - Configurable log retention policy. 77 58 78 ### ⚡ Lightweight & Minimal 59 79 Designed to deliver maximum security with minimal code. No bloat, no complexity. … … 104 124 == Changelog == 105 125 126 = 1.2.0 - 17/01/2026 = 127 - Added: User Session Management (View active sessions, remote logout, idle timeout) 128 - Added: Hardening & Firewall (Disable XML-RPC, File Editor, Version Hiding, User Enumeration) 129 - Added: User-Agent Blocking 130 - Added: Audit Logs for security events 131 - Fixed: Dark mode improvements 132 - Improved: UI enhancements 133 106 134 = 1.1.0 - 13/01/2026 = 107 135 - Added: Vulnerability Checker
Note: See TracChangeset
for help on using the changeset viewer.