(status)
| 84 | } |
| 85 | |
| 86 | function buildPersistentTokensKeyWarningHtml(status) { |
| 87 | if (!status || typeof status !== 'object') return ''; |
| 88 | |
| 89 | const needsAttention = !!status.needsAttention; |
| 90 | const autoGenerated = !!status.autoGenerated; |
| 91 | if (!needsAttention && !autoGenerated) { |
| 92 | return ''; |
| 93 | } |
| 94 | |
| 95 | const toneClass = needsAttention ? 'alert-warning' : 'alert-info'; |
| 96 | const title = needsAttention |
| 97 | ? 'Persistent token security warning' |
| 98 | : 'Persistent token key note'; |
| 99 | const warning = String(status.warning || '').trim(); |
| 100 | const recommendedAction = String(status.recommendedAction || '').trim(); |
| 101 | const source = String(status.source || '').trim(); |
| 102 | const canRotateInApp = needsAttention && source !== 'env'; |
| 103 | const blockedByEnv = needsAttention && source === 'env'; |
| 104 | |
| 105 | return ` |
| 106 | <div class="alert ${toneClass}" style="margin-bottom:12px; border-radius:8px;"> |
| 107 | <div style="font-weight:600; margin-bottom:4px;">${escapeHTML(title)}</div> |
| 108 | ${warning ? `<div>${escapeHTML(warning)}</div>` : ''} |
| 109 | ${recommendedAction ? `<div style="margin-top:6px;">${escapeHTML(recommendedAction)}</div>` : ''} |
| 110 | ${source ? `<div class="small" style="margin-top:6px;"><strong>Source:</strong> ${escapeHTML(source)}</div>` : ''} |
| 111 | ${canRotateInApp ? ` |
| 112 | <div style="margin-top:10px;"> |
| 113 | <button type="button" class="btn btn-sm btn-outline-danger" id="frRotatePersistentTokensKeyBtn"> |
| 114 | Rotate key now |
| 115 | </button> |
| 116 | <div class="small text-muted" style="margin-top:6px;"> |
| 117 | FileRise will generate a new key, re-encrypt stored secrets, and expire all remember-me sessions. Run this during a quiet maintenance window. |
| 118 | </div> |
| 119 | <div class="small text-muted" id="frRotatePersistentTokensKeyStatus" style="margin-top:4px;"></div> |
| 120 | </div> |
| 121 | ` : ''} |
| 122 | ${blockedByEnv ? ` |
| 123 | <div class="small text-muted" style="margin-top:10px;"> |
| 124 | In-app rotation is disabled while <code>PERSISTENT_TOKENS_KEY</code> is controlled by the container or host environment. Set the new key outside the Admin Panel and run rotation after upgrading to a build without the shipped placeholder. |
| 125 | </div> |
| 126 | ` : ''} |
| 127 | </div> |
| 128 | `; |
| 129 | } |
| 130 | |
| 131 | function wirePersistentTokensKeyWarningActions(status) { |
| 132 | const btn = document.getElementById('frRotatePersistentTokensKeyBtn'); |
no test coverage detected