mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 21:00:41 +00:00
feat: implement device login approval system
Add a complete device authentication approval flow that allows users to approve login requests from new devices on their already-authenticated devices. Core features: - Create authentication requests when logging in from new devices - Display pending requests with device info, IP address, and fingerprint phrases - Approve or deny requests from web interface with real-time notifications - Support multiple auth request types (authenticate & unlock, unlock only) - Automatic expiration and cleanup of stale requests Backend changes: - Add auth_requests table with proper indexes for efficient queries - Implement full CRUD API for authentication requests - Add notification hub integration for real-time updates - Add device fingerprint phrase generation for security verification Frontend changes: - Add AuthRequestApprovalDialog component for approving/denying requests - Add PendingAuthRequestsPanel component to display and manage pending requests - Integrate panels into Security and Settings pages - Add fingerprint wordlist for generating human-readable verification phrases - Update i18n translations for all supported languages Security considerations: - Access code verification to prevent unauthorized access - Device fingerprint validation for additional security layer - IP address and country tracking for audit purposes - Automatic expiration of old requests (15 minutes) - Only most recent request per device can be approved Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,14 +2,20 @@ import { useState } from 'preact/hooks';
|
||||
import { Clock3, Pencil, RefreshCw, ShieldCheck, ShieldOff, Trash2 } from 'lucide-preact';
|
||||
import ConfirmDialog from '@/components/ConfirmDialog';
|
||||
import LoadingState from '@/components/LoadingState';
|
||||
import type { AuthorizedDevice } from '@/lib/types';
|
||||
import PendingAuthRequestsPanel from '@/components/PendingAuthRequestsPanel';
|
||||
import type { AuthRequest, AuthorizedDevice } from '@/lib/types';
|
||||
import { t } from '@/lib/i18n';
|
||||
|
||||
interface SecurityDevicesPageProps {
|
||||
devices: AuthorizedDevice[];
|
||||
loading: boolean;
|
||||
error: string;
|
||||
pendingAuthRequests: AuthRequest[];
|
||||
pendingAuthRequestsLoading: boolean;
|
||||
onRefresh: () => void;
|
||||
onRefreshPendingAuthRequests: () => Promise<void>;
|
||||
onApproveAuthRequest: (request: AuthRequest) => Promise<void>;
|
||||
onDenyAuthRequest: (request: AuthRequest) => Promise<void>;
|
||||
onRenameDevice: (device: AuthorizedDevice, name: string) => Promise<void>;
|
||||
onRevokeTrust: (device: AuthorizedDevice) => void;
|
||||
onTrustPermanently: (device: AuthorizedDevice) => void;
|
||||
@@ -72,6 +78,16 @@ export default function SecurityDevicesPage(props: SecurityDevicesPageProps) {
|
||||
return (
|
||||
<>
|
||||
<div className="stack">
|
||||
<PendingAuthRequestsPanel
|
||||
className="card"
|
||||
loadingVariant="compact"
|
||||
pendingAuthRequests={props.pendingAuthRequests}
|
||||
pendingAuthRequestsLoading={props.pendingAuthRequestsLoading}
|
||||
onRefreshPendingAuthRequests={props.onRefreshPendingAuthRequests}
|
||||
onApproveAuthRequest={props.onApproveAuthRequest}
|
||||
onDenyAuthRequest={props.onDenyAuthRequest}
|
||||
/>
|
||||
|
||||
<section className="card">
|
||||
<div className="section-head">
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user