fix(web): coerce fingerprint_type to string; sync frontend types and tests
This commit is contained in:
@@ -224,7 +224,7 @@ const AttackerDetail: React.FC = () => {
|
||||
const groups: Record<string, any[]> = {};
|
||||
filteredFps.forEach((fp) => {
|
||||
const p = getPayload(fp);
|
||||
let fpType: string = p.fingerprint_type || 'unknown';
|
||||
let fpType: string = String(p.fingerprint_type || 'unknown');
|
||||
if (fpType === 'tls_certificate') {
|
||||
fpType = p.target_ip ? 'tls_certificate_active' : 'tls_certificate_passive';
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('nextSortState', () => {
|
||||
});
|
||||
|
||||
const cred = (over: Partial<CredentialEntry> = {}): CredentialEntry => ({
|
||||
id: '1', last_seen: '2026-05-01T00:00:00Z', decky_name: 'd1', service: 'ssh',
|
||||
id: 1, last_seen: '2026-05-01T00:00:00Z', decky_name: 'd1', service: 'ssh',
|
||||
attacker_ip: '1.2.3.4', principal: 'root', secret_sha256: 'a',
|
||||
secret_kind: 'plaintext', secret_printable: 'p', attempt_count: 5,
|
||||
...over,
|
||||
@@ -42,7 +42,7 @@ const cred = (over: Partial<CredentialEntry> = {}): CredentialEntry => ({
|
||||
|
||||
describe('sortCreds', () => {
|
||||
it('returns the input untouched for empty col', () => {
|
||||
const rows = [cred({ id: 'A' }), cred({ id: 'B' })];
|
||||
const rows = [cred({ id: 1 }), cred({ id: 2 })];
|
||||
expect(sortCreds(rows, '', 'asc')).toBe(rows);
|
||||
});
|
||||
it('sorts numbers numerically (asc/desc)', () => {
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
padding: 20px;
|
||||
height: 64px;
|
||||
flex-shrink: 0;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -66,6 +66,11 @@
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
html[data-theme="light"] .login-form input {
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
color: var(--ink, #1a1a1a);
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
color: #ff4141;
|
||||
font-size: 0.8rem;
|
||||
@@ -80,6 +85,7 @@
|
||||
margin-top: 8px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 2px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.login-footer {
|
||||
|
||||
@@ -7,9 +7,6 @@ import { useMazeContextMenu } from './useMazeContextMenu';
|
||||
import type { Net, MazeNode } from './types';
|
||||
import type { UseTopologyEditor } from './useTopologyEditor';
|
||||
|
||||
const noop = () => {};
|
||||
const noopAsync = async () => {};
|
||||
|
||||
const stubEditor = (): UseTopologyEditor => ({
|
||||
inFlight: 0,
|
||||
addLan: vi.fn(),
|
||||
@@ -43,7 +40,8 @@ const decky: MazeNode = {
|
||||
archetype: 'workstation', services: ['ssh'], status: 'idle', x: 0, y: 0,
|
||||
};
|
||||
const observed: MazeNode = {
|
||||
kind: 'observed', id: 'obs-1', label: '1.2.3.4', netId: 'lan-www',
|
||||
kind: 'observed', id: 'obs-1', netId: 'lan-www', name: '1.2.3.4',
|
||||
archetype: 'attacker-pool', services: ['*'], status: 'idle',
|
||||
x: 0, y: 0,
|
||||
};
|
||||
|
||||
@@ -51,7 +49,10 @@ const baseArgs = () => ({
|
||||
nets: [subnet, internet],
|
||||
nodes: [decky, observed],
|
||||
services: [
|
||||
{ slug: 'http', name: 'HTTP', proto: 'tcp', port: 80, icon: 'globe', risk: 'medium' as const },
|
||||
{
|
||||
slug: 'http', name: 'HTTP', proto: 'tcp' as const, port: 80,
|
||||
icon: 'globe', risk: 'med' as const, group: 'Web' as const,
|
||||
},
|
||||
],
|
||||
archetypes: [
|
||||
{ slug: 'workstation', name: 'Workstation', services: ['ssh'], icon: 'monitor' },
|
||||
|
||||
@@ -47,7 +47,7 @@ describe('coercePersona', () => {
|
||||
const r = coercePersona({
|
||||
name: 'a', email: 'a@b.c', role: 'r',
|
||||
tone: 'custom', tone_custom: long,
|
||||
mannerisms: Array.from({ length: 20 }, (_, i) => `m${i}`).concat([42, null]),
|
||||
mannerisms: Array.from({ length: 20 }, (_, i) => `m${i}`).concat(['42', ''] as string[]),
|
||||
});
|
||||
expect('ok' in r).toBe(true);
|
||||
if ('ok' in r) {
|
||||
|
||||
@@ -100,7 +100,7 @@ describe('useSwarmHosts', () => {
|
||||
});
|
||||
});
|
||||
expect(r?.ok).toBe(true);
|
||||
expect(r?.data?.host_uuid).toBe('h-9');
|
||||
expect(r?.ok && r.data?.host_uuid).toBe('h-9');
|
||||
});
|
||||
|
||||
it('polls /swarm/hosts every 10s', async () => {
|
||||
|
||||
@@ -3,11 +3,9 @@ import api from '../../utils/api';
|
||||
import { extractErrorDetail } from './helpers';
|
||||
import type { BundleRequest, BundleResult, SwarmHost } from './types';
|
||||
|
||||
export interface MutationResult<T = void> {
|
||||
ok: boolean;
|
||||
reason?: string;
|
||||
data?: T;
|
||||
}
|
||||
export type MutationResult<T = void> = T extends void
|
||||
? { ok: true } | { ok: false; reason: string }
|
||||
: { ok: true; data: T } | { ok: false; reason: string };
|
||||
|
||||
export interface UseSwarmHosts {
|
||||
hosts: SwarmHost[];
|
||||
|
||||
Reference in New Issue
Block a user