Plugin Directory

Changeset 3441244


Ignore:
Timestamp:
01/16/2026 08:03:48 PM (2 months ago)
Author:
nhrrob
Message:

Update to version 1.2.0 from GitHub

Location:
nhrrob-secure
Files:
14 added
24 edited
1 copied

Legend:

Unmodified
Added
Removed
  • nhrrob-secure/tags/1.2.0/assets/src/components/VulnerabilityChecker.js

    r3438122 r3441244  
    115115                                            <a href="plugins.php" style={{ textDecoration: 'none', color: 'inherit' }}>
    116116                                                {decodeEntities(plugin.name)}
    117                                             </a> 
     117                                            </a>
    118118                                            <span style={{ fontWeight: 'normal', color: '#666' }}> ({plugin.version})</span>
    119119                                        </strong>
  • nhrrob-secure/tags/1.2.0/assets/src/index.js

    r3438122 r3441244  
    1313import VulnerabilityChecker from './components/VulnerabilityChecker';
    1414import FileScanner from './components/FileScanner';
     15import Hardening from './components/Hardening';
     16import SessionManager from './components/SessionManager';
     17import AuditLog from './components/AuditLog';
    1518import './style.css';
    1619
     
    124127                <CustomLoginPage settings={settings} updateSetting={updateSetting} />
    125128                <TwoFactorAuth settings={settings} updateSetting={updateSetting} />
     129                <Hardening settings={settings} updateSetting={updateSetting} />
    126130                <FileProtection settings={settings} updateSetting={updateSetting} />
    127131                <VulnerabilityChecker />
    128132                <FileScanner />
     133                <SessionManager settings={settings} updateSetting={updateSetting} />
     134                <AuditLog settings={settings} updateSetting={updateSetting} />
    129135            </div>
    130136
     
    148154    render(<SettingsApp />, rootElement);
    149155}
    150 
  • nhrrob-secure/tags/1.2.0/assets/src/style.css

    r3438122 r3441244  
    134134    }
    135135
    136     .dark-mode .components-text-control__input {
     136    .dark-mode .components-text-control__input,
     137    .dark-mode .components-textarea-control__input {
    137138        background-color: #2c3338 !important;
    138139        border-color: #43494e !important;
    139140        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;
    140181    }
    141182
     
    358399    }
    359400}
     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  
    161161        justify-content: space-between;
    162162        gap: 1rem;
     163}
     164
     165    .nhrrob-secure-card-header-actions {
     166        display: flex;
     167        align-items: center;
     168        gap: 0.75rem;
    163169}
    164170
     
    181187    }
    182188
    183     .dark-mode .components-text-control__input {
     189    .dark-mode .components-text-control__input,
     190    .dark-mode .components-textarea-control__input {
    184191        background-color: #2c3338 !important;
    185192        border-color: #43494e !important;
    186193        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;
    187245    }
    188246
     
    394452}
    395453
     454    .dark-mode .session-item .nhrrob-secure-card-subtitle {
     455        color: var(--nhrrob-secure-text-muted);
     456    }
     457
    396458    .nhrrob-secure-card-subtitle {
    397459        margin: 0px;
     
    424486        background-color: transparent;
    425487}
     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    }
    426493
    427494    .nhrrob-result-group-title {
     
    471538}
    472539
     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
    473545    .nhrrob-result-row:hover {
    474546        --tw-bg-opacity: 1;
     
    501573        color: rgb(229 231 235 / var(--tw-text-opacity, 1));
    502574}
     575
     576    .dark-mode .session-item .nhrrob-file-meta {
     577        color: var(--nhrrob-secure-text-muted);
     578    }
    503579
    504580    .nhrrob-file-meta {
     
    538614        margin-bottom: 1rem;
    539615}
     616.ml-2 {
     617        margin-left: 0.5rem;
     618}
    540619.ml-5 {
    541620        margin-left: 1.25rem;
     
    544623        margin-top: 0px;
    545624}
     625.mt-1 {
     626        margin-top: 0.25rem;
     627}
    546628.mt-4 {
    547629        margin-top: 1rem;
    548630}
     631.block {
     632        display: block;
     633}
     634.flex {
     635        display: flex;
     636}
    549637.table {
    550638        display: table;
     
    556644        display: none;
    557645}
     646.w-64 {
     647        width: 16rem;
     648}
     649.w-full {
     650        width: 100%;
     651}
    558652.grid-cols-2 {
    559653        grid-template-columns: repeat(2, minmax(0, 1fr));
    560654}
     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}
    561664.gap-2 {
    562665        gap: 0.5rem;
    563666}
     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}
    564681.border-t {
    565682        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));
    566687}
    567688.border-gray-100 {
     
    569690        border-color: rgb(243 244 246 / var(--tw-border-opacity, 1));
    570691}
     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}
    571722.pt-4 {
    572723        padding-top: 1rem;
     724}
     725.font-mono {
     726        font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
    573727}
    574728.text-sm {
     
    580734        line-height: 1rem;
    581735}
     736.font-medium {
     737        font-weight: 500;
     738}
    582739.font-semibold {
    583740        font-weight: 600;
    584741}
     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}
    585750.text-gray-500 {
    586751        --tw-text-opacity: 1;
    587752        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));
    588757}
    589758.filter {
     
    608777        }
    609778}
     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  
    280280    margin-bottom: 1rem
    281281}
     282.ml-2 {
     283
     284    margin-left: 0.5rem
     285}
    282286.ml-5 {
    283287
     
    288292    margin-top: 0px
    289293}
     294.mt-1 {
     295
     296    margin-top: 0.25rem
     297}
    290298.mt-4 {
    291299
    292300    margin-top: 1rem
    293301}
     302.block {
     303
     304    display: block
     305}
     306.flex {
     307
     308    display: flex
     309}
    294310.table {
    295311
     
    304320    display: none
    305321}
     322.w-64 {
     323
     324    width: 16rem
     325}
     326.w-full {
     327
     328    width: 100%
     329}
    306330.grid-cols-2 {
    307331
    308332    grid-template-columns: repeat(2, minmax(0, 1fr))
    309333}
     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}
    310346.gap-2 {
    311347
    312348    gap: 0.5rem
    313349}
     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}
    314370.border-t {
    315371
    316372    border-top-width: 1px
    317373}
     374.border-blue-200 {
     375
     376    --tw-border-opacity: 1;
     377
     378    border-color: rgb(191 219 254 / var(--tw-border-opacity, 1))
     379}
    318380.border-gray-100 {
    319381
     
    322384    border-color: rgb(243 244 246 / var(--tw-border-opacity, 1))
    323385}
     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}
    324430.pt-4 {
    325431
    326432    padding-top: 1rem
    327433}
     434.font-mono {
     435
     436    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace
     437}
    328438.text-sm {
    329439
     
    338448    line-height: 1rem
    339449}
     450.font-medium {
     451
     452    font-weight: 500
     453}
    340454.font-semibold {
    341455
    342456    font-weight: 600
    343457}
     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}
    344470.text-gray-500 {
    345471
     
    348474    color: rgb(107 114 128 / var(--tw-text-opacity, 1))
    349475}
     476.text-gray-700 {
     477
     478    --tw-text-opacity: 1;
     479
     480    color: rgb(55 65 81 / var(--tw-text-opacity, 1))
     481}
    350482.filter {
    351483
  • nhrrob-secure/tags/1.2.0/includes/Admin/Api.php

    r3438122 r3441244  
    9090                    'sanitize_callback' => 'rest_sanitize_boolean',
    9191                ],
     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                ],
    92120            ],
    93121        ]);
     
    161189        ]);
    162190
     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        ]);
    163233    }
    164234
     
    179249            'nhrrob_secure_2fa_type' => get_option('nhrrob_secure_2fa_type', 'app'),
    180250            '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),
    181258            'available_roles' => $this->get_available_roles(),
    182259        ];
     
    268345        $scanner = new \NHRRob\Secure\FileScanner();
    269346        $result = $scanner->repair_core_file($file);
    270        
     347
    271348        if (is_wp_error($result)) {
    272349            return $result;
    273350        }
    274        
     351
    275352        return ['success' => true, 'message' => 'File repaired successfully.'];
    276353    }
     
    283360        $file = $request->get_param('file');
    284361        $scanner = new \NHRRob\Secure\FileScanner();
    285        
     362
    286363        // Security check: ensure file is inside WP_CONTENT_DIR
    287364        if (strpos($file, WP_CONTENT_DIR) !== 0) {
     
    290367
    291368        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
    295372        return new \WP_Error('delete_failed', 'Could not delete file.');
    296373    }
     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    }
    297432}
  • nhrrob-secure/tags/1.2.0/includes/App.php

    r3435758 r3441244  
    66 * App base class
    77 */
    8 class App {
     8class App
     9{
     10    /**
     11     * Initialize the class
     12     */
     13    public function __construct()
     14    {
     15        // Base init
     16    }
     17
    918    /**
    1019     * Render a template
     
    1322     * @param array $args
    1423     */
    15     public function render( $name, $args = [] ) {
    16         extract( $args );
     24    public function render($name, $args = [])
     25    {
     26        extract($args);
    1727        $template = NHRROB_SECURE_PATH . '/templates/' . $name . '.php';
    1828
    19         if ( file_exists( $template ) ) {
     29        if (file_exists($template)) {
    2030            include $template;
    2131        }
  • nhrrob-secure/tags/1.2.0/nhrrob-secure.php

    r3438122 r3441244  
    11<?php
    22/**
    3  * Plugin Name: NHR Secure – Hide Admin, Limit Login, 2FA & Vulnerability Checker
     3 * Plugin Name: NHR Secure – Login Security, Firewall, 2FA & Audit Log
    44 * Plugin URI: http://wordpress.org/plugins/nhrrob-secure/
    55 * Description: Lightweight WordPress security plugin that protects your admin area, hides debug logs, limits login attempts, and checks for vulnerabilities. Minimal code, maximum protection.
    66 * Author: Nazmul Hasan Robin
    77 * Author URI: https://profiles.wordpress.org/nhrrob/
    8  * Version: 1.1.0
     8 * Version: 1.2.0
    99 * Requires at least: 6.0
    1010 * Requires PHP: 7.4
     
    3131     * @var string
    3232     */
    33     const version = '1.1.0';
     33    const version = '1.2.0';
    3434
    3535    /**
     
    103103        new \NHRRob\Secure\FileScanner();
    104104
     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
    105114        // Initialize admin menu
    106115        if (is_admin()) {
     
    119128            wp_schedule_event(time(), 'daily', 'nhrrob_secure_vulnerability_scan_cron');
    120129        }
     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();
    121137    }
    122138
     
    129145    {
    130146        wp_clear_scheduled_hook('nhrrob_secure_vulnerability_scan_cron');
     147        wp_clear_scheduled_hook('nhrrob_secure_daily_cleanup');
    131148    }
    132149}
  • 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 ===
    22Contributors: nhrrob
    33Tags: security, hide admin, login protection, debug log, 2fa
     
    55Tested up to: 6.9
    66Requires PHP: 7.4
    7 Stable tag: 1.1.0
     7Stable tag: 1.2.0
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    5656- Check file integrity
    5757
     58### 🖥️ User Session Management
     59Monitor 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
     65Essential 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
     73Keep 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
    5878### ⚡ Lightweight & Minimal
    5979Designed to deliver maximum security with minimal code. No bloat, no complexity.
     
    104124== Changelog ==
    105125
     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
    106134= 1.1.0 - 13/01/2026 =
    107135- Added: Vulnerability Checker
  • nhrrob-secure/trunk/assets/src/components/VulnerabilityChecker.js

    r3438122 r3441244  
    115115                                            <a href="plugins.php" style={{ textDecoration: 'none', color: 'inherit' }}>
    116116                                                {decodeEntities(plugin.name)}
    117                                             </a> 
     117                                            </a>
    118118                                            <span style={{ fontWeight: 'normal', color: '#666' }}> ({plugin.version})</span>
    119119                                        </strong>
  • nhrrob-secure/trunk/assets/src/index.js

    r3438122 r3441244  
    1313import VulnerabilityChecker from './components/VulnerabilityChecker';
    1414import FileScanner from './components/FileScanner';
     15import Hardening from './components/Hardening';
     16import SessionManager from './components/SessionManager';
     17import AuditLog from './components/AuditLog';
    1518import './style.css';
    1619
     
    124127                <CustomLoginPage settings={settings} updateSetting={updateSetting} />
    125128                <TwoFactorAuth settings={settings} updateSetting={updateSetting} />
     129                <Hardening settings={settings} updateSetting={updateSetting} />
    126130                <FileProtection settings={settings} updateSetting={updateSetting} />
    127131                <VulnerabilityChecker />
    128132                <FileScanner />
     133                <SessionManager settings={settings} updateSetting={updateSetting} />
     134                <AuditLog settings={settings} updateSetting={updateSetting} />
    129135            </div>
    130136
     
    148154    render(<SettingsApp />, rootElement);
    149155}
    150 
  • nhrrob-secure/trunk/assets/src/style.css

    r3438122 r3441244  
    134134    }
    135135
    136     .dark-mode .components-text-control__input {
     136    .dark-mode .components-text-control__input,
     137    .dark-mode .components-textarea-control__input {
    137138        background-color: #2c3338 !important;
    138139        border-color: #43494e !important;
    139140        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;
    140181    }
    141182
     
    358399    }
    359400}
     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  
    161161        justify-content: space-between;
    162162        gap: 1rem;
     163}
     164
     165    .nhrrob-secure-card-header-actions {
     166        display: flex;
     167        align-items: center;
     168        gap: 0.75rem;
    163169}
    164170
     
    181187    }
    182188
    183     .dark-mode .components-text-control__input {
     189    .dark-mode .components-text-control__input,
     190    .dark-mode .components-textarea-control__input {
    184191        background-color: #2c3338 !important;
    185192        border-color: #43494e !important;
    186193        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;
    187245    }
    188246
     
    394452}
    395453
     454    .dark-mode .session-item .nhrrob-secure-card-subtitle {
     455        color: var(--nhrrob-secure-text-muted);
     456    }
     457
    396458    .nhrrob-secure-card-subtitle {
    397459        margin: 0px;
     
    424486        background-color: transparent;
    425487}
     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    }
    426493
    427494    .nhrrob-result-group-title {
     
    471538}
    472539
     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
    473545    .nhrrob-result-row:hover {
    474546        --tw-bg-opacity: 1;
     
    501573        color: rgb(229 231 235 / var(--tw-text-opacity, 1));
    502574}
     575
     576    .dark-mode .session-item .nhrrob-file-meta {
     577        color: var(--nhrrob-secure-text-muted);
     578    }
    503579
    504580    .nhrrob-file-meta {
     
    538614        margin-bottom: 1rem;
    539615}
     616.ml-2 {
     617        margin-left: 0.5rem;
     618}
    540619.ml-5 {
    541620        margin-left: 1.25rem;
     
    544623        margin-top: 0px;
    545624}
     625.mt-1 {
     626        margin-top: 0.25rem;
     627}
    546628.mt-4 {
    547629        margin-top: 1rem;
    548630}
     631.block {
     632        display: block;
     633}
     634.flex {
     635        display: flex;
     636}
    549637.table {
    550638        display: table;
     
    556644        display: none;
    557645}
     646.w-64 {
     647        width: 16rem;
     648}
     649.w-full {
     650        width: 100%;
     651}
    558652.grid-cols-2 {
    559653        grid-template-columns: repeat(2, minmax(0, 1fr));
    560654}
     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}
    561664.gap-2 {
    562665        gap: 0.5rem;
    563666}
     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}
    564681.border-t {
    565682        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));
    566687}
    567688.border-gray-100 {
     
    569690        border-color: rgb(243 244 246 / var(--tw-border-opacity, 1));
    570691}
     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}
    571722.pt-4 {
    572723        padding-top: 1rem;
     724}
     725.font-mono {
     726        font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
    573727}
    574728.text-sm {
     
    580734        line-height: 1rem;
    581735}
     736.font-medium {
     737        font-weight: 500;
     738}
    582739.font-semibold {
    583740        font-weight: 600;
    584741}
     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}
    585750.text-gray-500 {
    586751        --tw-text-opacity: 1;
    587752        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));
    588757}
    589758.filter {
     
    608777        }
    609778}
     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  
    280280    margin-bottom: 1rem
    281281}
     282.ml-2 {
     283
     284    margin-left: 0.5rem
     285}
    282286.ml-5 {
    283287
     
    288292    margin-top: 0px
    289293}
     294.mt-1 {
     295
     296    margin-top: 0.25rem
     297}
    290298.mt-4 {
    291299
    292300    margin-top: 1rem
    293301}
     302.block {
     303
     304    display: block
     305}
     306.flex {
     307
     308    display: flex
     309}
    294310.table {
    295311
     
    304320    display: none
    305321}
     322.w-64 {
     323
     324    width: 16rem
     325}
     326.w-full {
     327
     328    width: 100%
     329}
    306330.grid-cols-2 {
    307331
    308332    grid-template-columns: repeat(2, minmax(0, 1fr))
    309333}
     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}
    310346.gap-2 {
    311347
    312348    gap: 0.5rem
    313349}
     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}
    314370.border-t {
    315371
    316372    border-top-width: 1px
    317373}
     374.border-blue-200 {
     375
     376    --tw-border-opacity: 1;
     377
     378    border-color: rgb(191 219 254 / var(--tw-border-opacity, 1))
     379}
    318380.border-gray-100 {
    319381
     
    322384    border-color: rgb(243 244 246 / var(--tw-border-opacity, 1))
    323385}
     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}
    324430.pt-4 {
    325431
    326432    padding-top: 1rem
    327433}
     434.font-mono {
     435
     436    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace
     437}
    328438.text-sm {
    329439
     
    338448    line-height: 1rem
    339449}
     450.font-medium {
     451
     452    font-weight: 500
     453}
    340454.font-semibold {
    341455
    342456    font-weight: 600
    343457}
     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}
    344470.text-gray-500 {
    345471
     
    348474    color: rgb(107 114 128 / var(--tw-text-opacity, 1))
    349475}
     476.text-gray-700 {
     477
     478    --tw-text-opacity: 1;
     479
     480    color: rgb(55 65 81 / var(--tw-text-opacity, 1))
     481}
    350482.filter {
    351483
  • nhrrob-secure/trunk/includes/Admin/Api.php

    r3438122 r3441244  
    9090                    'sanitize_callback' => 'rest_sanitize_boolean',
    9191                ],
     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                ],
    92120            ],
    93121        ]);
     
    161189        ]);
    162190
     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        ]);
    163233    }
    164234
     
    179249            'nhrrob_secure_2fa_type' => get_option('nhrrob_secure_2fa_type', 'app'),
    180250            '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),
    181258            'available_roles' => $this->get_available_roles(),
    182259        ];
     
    268345        $scanner = new \NHRRob\Secure\FileScanner();
    269346        $result = $scanner->repair_core_file($file);
    270        
     347
    271348        if (is_wp_error($result)) {
    272349            return $result;
    273350        }
    274        
     351
    275352        return ['success' => true, 'message' => 'File repaired successfully.'];
    276353    }
     
    283360        $file = $request->get_param('file');
    284361        $scanner = new \NHRRob\Secure\FileScanner();
    285        
     362
    286363        // Security check: ensure file is inside WP_CONTENT_DIR
    287364        if (strpos($file, WP_CONTENT_DIR) !== 0) {
     
    290367
    291368        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
    295372        return new \WP_Error('delete_failed', 'Could not delete file.');
    296373    }
     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    }
    297432}
  • nhrrob-secure/trunk/includes/App.php

    r3435758 r3441244  
    66 * App base class
    77 */
    8 class App {
     8class App
     9{
     10    /**
     11     * Initialize the class
     12     */
     13    public function __construct()
     14    {
     15        // Base init
     16    }
     17
    918    /**
    1019     * Render a template
     
    1322     * @param array $args
    1423     */
    15     public function render( $name, $args = [] ) {
    16         extract( $args );
     24    public function render($name, $args = [])
     25    {
     26        extract($args);
    1727        $template = NHRROB_SECURE_PATH . '/templates/' . $name . '.php';
    1828
    19         if ( file_exists( $template ) ) {
     29        if (file_exists($template)) {
    2030            include $template;
    2131        }
  • nhrrob-secure/trunk/nhrrob-secure.php

    r3438122 r3441244  
    11<?php
    22/**
    3  * Plugin Name: NHR Secure – Hide Admin, Limit Login, 2FA & Vulnerability Checker
     3 * Plugin Name: NHR Secure – Login Security, Firewall, 2FA & Audit Log
    44 * Plugin URI: http://wordpress.org/plugins/nhrrob-secure/
    55 * Description: Lightweight WordPress security plugin that protects your admin area, hides debug logs, limits login attempts, and checks for vulnerabilities. Minimal code, maximum protection.
    66 * Author: Nazmul Hasan Robin
    77 * Author URI: https://profiles.wordpress.org/nhrrob/
    8  * Version: 1.1.0
     8 * Version: 1.2.0
    99 * Requires at least: 6.0
    1010 * Requires PHP: 7.4
     
    3131     * @var string
    3232     */
    33     const version = '1.1.0';
     33    const version = '1.2.0';
    3434
    3535    /**
     
    103103        new \NHRRob\Secure\FileScanner();
    104104
     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
    105114        // Initialize admin menu
    106115        if (is_admin()) {
     
    119128            wp_schedule_event(time(), 'daily', 'nhrrob_secure_vulnerability_scan_cron');
    120129        }
     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();
    121137    }
    122138
     
    129145    {
    130146        wp_clear_scheduled_hook('nhrrob_secure_vulnerability_scan_cron');
     147        wp_clear_scheduled_hook('nhrrob_secure_daily_cleanup');
    131148    }
    132149}
  • 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 ===
    22Contributors: nhrrob
    33Tags: security, hide admin, login protection, debug log, 2fa
     
    55Tested up to: 6.9
    66Requires PHP: 7.4
    7 Stable tag: 1.1.0
     7Stable tag: 1.2.0
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    5656- Check file integrity
    5757
     58### 🖥️ User Session Management
     59Monitor 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
     65Essential 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
     73Keep 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
    5878### ⚡ Lightweight & Minimal
    5979Designed to deliver maximum security with minimal code. No bloat, no complexity.
     
    104124== Changelog ==
    105125
     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
    106134= 1.1.0 - 13/01/2026 =
    107135- Added: Vulnerability Checker
Note: See TracChangeset for help on using the changeset viewer.