Files

301 lines
13 KiB
PHP

<?php
declare(strict_types=1);
style('qortal_integration', 'personal');
script('qortal_integration', 'personal');
$sovereignMode = (string)($_['sovereignMode'] ?? 'powered');
$isPoweredMode = $sovereignMode !== 'full_qortal';
?>
<div
id="qortal-personal-root"
class="section"
data-user-mappings-url="<?php p($_['userMappingsUrl']); ?>"
data-user-create-wallet-url="<?php p($_['userCreateWalletUrl']); ?>"
data-user-backup-wallet-url="<?php p($_['userBackupWalletUrl']); ?>"
data-user-import-seed-link-url="<?php p($_['userImportSeedLinkUrl']); ?>"
data-user-import-backup-link-url="<?php p($_['userImportBackupLinkUrl']); ?>"
data-user-recovery-status-url="<?php p($_['userRecoveryStatusUrl']); ?>"
data-user-recovery-enroll-url="<?php p($_['userRecoveryEnrollUrl']); ?>"
data-user-recovery-disable-url="<?php p($_['userRecoveryDisableUrl']); ?>"
data-user-recovery-reveal-url="<?php p($_['userRecoveryRevealUrl']); ?>"
data-user-recovery-complete-emergency-url="<?php p($_['userRecoveryCompleteEmergencyUrl']); ?>"
data-user-unlink-mapping-url="<?php p($_['userUnlinkMappingUrl']); ?>"
data-user-qapps-prefs-url="<?php p($_['userQappsPrefsUrl']); ?>"
data-user-qapps-rules-url="<?php p($_['userQappsRulesUrl']); ?>"
data-user-qapps-rule-revoke-url="<?php p($_['userQappsRuleRevokeUrl']); ?>"
data-user-qapps-approval-mode="<?php p((string)($_['userQappsApprovalMode'] ?? 'once')); ?>"
data-user-qapps-approval-temp-minutes="<?php p((string)($_['userQappsApprovalTempMinutes'] ?? 120)); ?>"
data-user-qapps-approval-unlock-10-min="<?php p(!empty($_['userQappsApprovalUnlock10Min']) ? '1' : '0'); ?>"
data-user-qapps-unlock-session-20-min="<?php p(!empty($_['userQappsUnlockSession20Min']) ? '1' : '0'); ?>"
data-qapps-advanced-unlock-settings-enabled="<?php p(!empty($_['qappsAdvancedUnlockSettingsEnabled']) ? '1' : '0'); ?>"
data-user-talk-bridge-auto-approve-send-chat-message="<?php p(!empty($_['userTalkBridgeAutoApproveSendChatMessage']) ? '1' : '0'); ?>"
data-user-qapps-high-risk-confirmation-enabled="<?php p(!empty($_['userQappsHighRiskConfirmationEnabled']) ? '1' : '0'); ?>"
data-sovereign-mode="<?php p((string)($_['sovereignMode'] ?? 'powered')); ?>"
>
<h2 id="qortal-personal-title"><?php p($_['title']); ?></h2>
<p id="qortal-personal-help" class="qortal-help">
Import an existing account by seed phrase or backup JSON to link it with your profile.
</p>
<?php if (!empty($_['currentUserId'])): ?>
<p class="qortal-note">
Current Nextcloud user:
<code><?php p($_['currentUserId']); ?></code>
</p>
<?php endif; ?>
<div class="qortal-card qortal-full-only<?php if (empty($_['qappsAdvancedUnlockSettingsEnabled'])) { print_unescaped(' qortal-hidden'); } ?>" id="qortal-user-approval-defaults">
<h3>Default Unlock Window</h3>
<p class="qortal-note">
These settings control how long the wallet stays unlocked after you enter your password. Request approvals are handled automatically while the wallet is unlocked.
</p>
<div class="qortal-grid">
<label for="qortal-default-approval-mode">Default Unlock Window</label>
<select id="qortal-default-approval-mode">
<option value="60">1 hour</option>
<option value="120">2 hours</option>
<option value="180">3 hours</option>
<option value="360">6 hours</option>
<option value="720">12 hours</option>
<option value="1440">24 hours</option>
<option value="7200">Max (120 hours)</option>
</select>
<input id="qortal-default-approval-temp-minutes" type="hidden" value="120">
</div>
<div class="qortal-toggles">
<label>
<input id="qortal-default-talk-bridge-auto-approve-send-chat-message" type="checkbox">
Auto-approve Talk bridge `SEND_CHAT_MESSAGE` for this user
</label>
<label>
<input id="qortal-high-risk-confirmation-enabled" type="checkbox">
Require an extra confirmation for high-risk Q-App requests
</label>
</div>
<div class="qortal-toggles qortal-hidden">
<label>
<input id="qortal-default-approval-unlock-10-min" type="checkbox">
Default to "Also unlock wallet for 1 hour"
</label>
<label>
<input id="qortal-default-unlock-session-20-min" type="checkbox">
Default to "Keep wallet unlocked for 1 hour" on unlock popup
</label>
</div>
<div class="qortal-actions">
<button id="qortal-save-approval-defaults" class="button button-primary">Save Unlock Window</button>
<button id="qortal-reset-approval-defaults" class="button">Reset to Default Window</button>
</div>
<div id="qortal-approval-defaults-result" class="qortal-status qortal-compact-status"></div>
</div>
<div class="qortal-card qortal-full-only qortal-hidden" id="qortal-user-approval-rules">
<h3>Active Q-Apps Approval Rules</h3>
<p class="qortal-note">
Only persistent rules set from Q-Apps approval prompts are listed here. Temporary X-minute approvals stay in the current browser tab only. Removing a rule sets that scope back to ask every time.
</p>
<div class="qortal-actions">
<button id="qortal-refresh-approval-rules" class="button">Refresh Rules</button>
</div>
<div class="qortal-table-wrap">
<table class="qortal-table">
<thead>
<tr>
<th>Mode</th>
<th>App</th>
<th>Scope</th>
<th>Request Type</th>
<th>Updated</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="qortal-user-approval-rules-body"></tbody>
</table>
</div>
<div id="qortal-approval-rules-result" class="qortal-status qortal-compact-status"></div>
</div>
<div class="qortal-card" id="qortal-create-wallet">
<h3>Create New Account</h3>
<p class="qortal-note">
Create a new account locally and link it to your profile.
After creation you can generate and save a backup JSON.
</p>
<div class="qortal-grid">
<label for="qortal-create-password">Account Password</label>
<input id="qortal-create-password" type="password" placeholder="Required for account creation">
<label for="qortal-create-kdf">KDF Threads (optional)</label>
<input id="qortal-create-kdf" type="number" min="1" placeholder="Optional">
</div>
<div class="qortal-actions">
<button id="qortal-create-wallet-button" class="button button-primary">Create Account</button>
</div>
<div id="qortal-create-wallet-result" class="qortal-status qortal-compact-status"></div>
</div>
<div class="qortal-card" id="qortal-backup-wallet">
<h3>Backup Account</h3>
<p class="qortal-note">
Select a linked account, enter your current backup password, and download an encrypted backup JSON.
</p>
<div class="qortal-grid">
<label for="qortal-backup-wallet-select">Linked Account</label>
<select id="qortal-backup-wallet-select">
<option value="">Loading linked accounts…</option>
</select>
<label for="qortal-backup-wallet-password">Backup Password</label>
<input id="qortal-backup-wallet-password" type="password" placeholder="Current backup password">
</div>
<div class="qortal-toggles">
<label>
<input id="qortal-backup-reencrypt-toggle" type="checkbox">
Re-encrypt backup with a different password
</label>
</div>
<div id="qortal-backup-reencrypt-fields" class="qortal-grid qortal-hidden">
<label for="qortal-backup-new-password">New Backup Password</label>
<input id="qortal-backup-new-password" type="password" autocomplete="new-password" placeholder="Required when re-encrypt is enabled">
<label for="qortal-backup-new-password-confirm">Confirm New Backup Password</label>
<input id="qortal-backup-new-password-confirm" type="password" autocomplete="new-password" placeholder="Re-enter new password">
</div>
<div class="qortal-toggles">
<label>
<input id="qortal-backup-download" type="checkbox" checked>
Download backup JSON
</label>
<label>
<input id="qortal-backup-save" type="checkbox">
Save backup to Nextcloud Files
</label>
</div>
<div class="qortal-actions">
<button id="qortal-backup-wallet-button" class="button">Create Backup</button>
</div>
<div id="qortal-backup-result" class="qortal-status qortal-compact-status"></div>
</div>
<div class="qortal-card" id="qortal-managed-recovery">
<h3><?php p($isPoweredMode ? 'Managed Recovery (Optional)' : 'Managed Recovery (Optional)'); ?></h3>
<p class="qortal-note">
Opt-in only. This stores an encrypted recovery package so admins can assist account recovery without seeing your backup password directly.
Recovery requires both your passphrase and an admin-issued recovery code.
</p>
<div id="qortal-recovery-status" class="qortal-note"></div>
<div class="qortal-grid">
<label for="qortal-recovery-wallet-select">Linked Account</label>
<select id="qortal-recovery-wallet-select">
<option value="">Loading linked accounts…</option>
</select>
<label for="qortal-recovery-current-password">Current Backup Password</label>
<input id="qortal-recovery-current-password" type="password" autocomplete="current-password" placeholder="Current backup password">
<label for="qortal-recovery-passphrase">Recovery Passphrase</label>
<input id="qortal-recovery-passphrase" type="password" autocomplete="new-password" placeholder="Used with admin code for recovery">
<label for="qortal-recovery-passphrase-confirm">Confirm Recovery Passphrase</label>
<input id="qortal-recovery-passphrase-confirm" type="password" autocomplete="new-password" placeholder="Re-enter recovery passphrase">
</div>
<div class="qortal-toggles">
<label>
<input id="qortal-recovery-enable-managed" type="checkbox">
Enable managed recovery escrow for this account
</label>
<label>
<input id="qortal-recovery-enable-emergency-login" type="checkbox">
Allow admin emergency temporary login reset for this account
</label>
</div>
<div class="qortal-actions">
<button id="qortal-recovery-save-button" class="button button-primary">Save Recovery Settings</button>
<button id="qortal-recovery-disable-button" class="button">Disable Managed Recovery</button>
</div>
<hr class="qortal-separator">
<p class="qortal-note">
If an admin gives you a recovery code, enter it with your recovery passphrase to reveal your current backup password once.
</p>
<div class="qortal-grid">
<label for="qortal-recovery-admin-code">Admin Recovery Code</label>
<input id="qortal-recovery-admin-code" type="text" spellcheck="false" autocomplete="off" placeholder="RCV-...">
</div>
<div class="qortal-actions">
<button id="qortal-recovery-reveal-button" class="button">Reveal Backup Password</button>
<button id="qortal-recovery-complete-emergency-button" class="button">I Replaced Backup Password</button>
</div>
<div id="qortal-recovery-result" class="qortal-status qortal-compact-status"></div>
</div>
<div class="qortal-card">
<h3>Import Existing Account</h3>
<p class="qortal-note">
This imports your account into the broker's External Auth context and links it to your current Nextcloud user.
</p>
<div class="qortal-grid">
<label for="qortal-seed-phrase">Seed Phrase</label>
<textarea id="qortal-seed-phrase" rows="3" spellcheck="false" placeholder="word1 word2 ..."></textarea>
<label for="qortal-wallet-password">Account Password</label>
<input id="qortal-wallet-password" type="password" placeholder="Password to encrypt imported account">
</div>
<div class="qortal-actions">
<button id="qortal-import-link" class="button button-primary">Import And Link</button>
<button id="qortal-refresh-user-mappings" class="button">Refresh My Linked Accounts</button>
</div>
</div>
<div class="qortal-card">
<h3>Import Backup JSON</h3>
<p class="qortal-note">
Upload your encrypted Qortal wallet backup JSON and provide its password.
</p>
<div class="qortal-grid">
<label for="qortal-backup-file">Backup JSON File</label>
<input id="qortal-backup-file" type="file" accept=".json,application/json">
<label for="qortal-backup-password">Backup Password</label>
<input id="qortal-backup-password" type="password" placeholder="Password used when creating backup">
</div>
<div class="qortal-actions">
<button id="qortal-import-backup-link" class="button button-primary">Import Backup And Link</button>
</div>
</div>
<div id="qortal-personal-feedback" class="qortal-feedback" role="status"></div>
<div id="qortal-personal-success" class="qortal-note"></div>
<pre id="qortal-personal-result" class="qortal-status"></pre>
<div class="qortal-card">
<h3><?php p($isPoweredMode ? 'My Linked Accounts' : 'My Linked Qortal Accounts'); ?></h3>
<div class="qortal-table-wrap">
<table class="qortal-table">
<thead>
<tr>
<th>Qortal Address</th>
<th>Account ID</th>
<th>Status</th>
<th>Updated</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="qortal-user-mappings-body"></tbody>
</table>
</div>
</div>
<?php if (!empty($_['qappsEnabled']) || !empty($_['qappsFullBrowserEnabled'])): ?>
<div class="qortal-card">
<h3><?php p($isPoweredMode ? 'NuQloud Apps Access' : 'Q-Apps Access'); ?></h3>
<p class="qortal-note">
<?php p($isPoweredMode ? 'Launch approved NuQloud Apps from the NuQloud Apps hub.' : 'Launch approved Q-Apps from the Q-Apps hub.'); ?>
</p>
<a class="button button-primary" href="<?php p($_['qappsUrl']); ?>"><?php p($isPoweredMode ? 'Open NuQloud Apps Hub' : 'Open Q-Apps Hub'); ?></a>
</div>
<?php endif; ?>
</div>