Files
osint/resources/views/investigations/show.blade.php
T
cedry2k1992andClaude Sonnet 5 873699e23e Initial commit: Laravel OSINT platform
Multi-user OSINT investigation tool with owner-controlled per-user and
per-group access grants. Includes Sherlock, theHarvester, crt.sh, WHOIS,
and ip-api.com collectors wired through a pluggable Runner/queue pipeline,
investigation search, and printable/CSV/JSON reporting.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 10:22:05 +03:00

187 lines
12 KiB
PHP

<x-app-layout>
<x-slot name="header">
<div class="flex justify-between items-start">
<div>
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ $investigation->name }}
</h2>
<p class="text-sm text-gray-500 dark:text-gray-400">
{{ __('Owned by') }} {{ $investigation->owner->name }} &middot; {{ $investigation->status }}
</p>
</div>
<div class="flex items-center gap-4">
<a href="{{ route('investigations.report', $investigation) }}" class="text-sm text-indigo-600 dark:text-indigo-400 hover:underline">
{{ __('Report') }}
</a>
<a href="{{ route('investigations.export.csv', $investigation) }}" class="text-sm text-indigo-600 dark:text-indigo-400 hover:underline">
{{ __('Export CSV') }}
</a>
<a href="{{ route('investigations.export.json', $investigation) }}" class="text-sm text-indigo-600 dark:text-indigo-400 hover:underline">
{{ __('Export JSON') }}
</a>
@if ($canManageAccess)
<a href="{{ route('investigations.access.index', $investigation) }}" class="text-sm text-indigo-600 dark:text-indigo-400 hover:underline">
{{ __('Manage access') }}
</a>
<form method="POST" action="{{ route('investigations.destroy', $investigation) }}" onsubmit="return confirm('{{ __('Delete this investigation and all its targets/findings?') }}');">
@csrf
@method('DELETE')
<button type="submit" class="text-sm text-red-600 dark:text-red-400 hover:underline">{{ __('Delete') }}</button>
</form>
@endif
</div>
</div>
</x-slot>
<div class="py-12">
<div class="max-w-5xl mx-auto sm:px-6 lg:px-8 space-y-6">
@if (session('status'))
<div class="bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 text-sm rounded-md p-4">
{{ session('status') }}
</div>
@endif
@if ($errors->any())
<div class="bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 text-sm rounded-md p-4">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@if ($investigation->description)
<div class="bg-white dark:bg-gray-800 shadow-sm sm:rounded-lg p-6 text-gray-700 dark:text-gray-300">
{{ $investigation->description }}
</div>
@endif
<div class="bg-white dark:bg-gray-800 shadow-sm sm:rounded-lg p-6">
<h3 class="font-semibold text-gray-800 dark:text-gray-200 mb-4">{{ __('Targets') }}</h3>
@forelse ($investigation->targets as $target)
<div class="border-t border-gray-200 dark:border-gray-700 py-4 first:border-t-0 first:pt-0">
<div class="flex justify-between items-start">
<div>
<span class="text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400">{{ $target->type }}</span>
<p class="font-medium text-gray-900 dark:text-gray-100">{{ $target->value }}</p>
@if ($target->notes)
<p class="text-sm text-gray-500 dark:text-gray-400">{{ $target->notes }}</p>
@endif
</div>
@if ($canEdit)
@php
$applicableSources = $sources->filter(fn ($s) => in_array($target->type, $s->target_types, true));
@endphp
<div class="flex items-center gap-3">
@if ($applicableSources->isNotEmpty())
<form method="POST" action="{{ route('investigations.targets.run', [$investigation, $target]) }}" class="flex items-center gap-2">
@csrf
<select name="source_id" class="text-sm border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 rounded-md">
@foreach ($applicableSources as $source)
<option value="{{ $source->id }}" @disabled(!$runnableSourceKeys->contains($source->key))>
{{ $source->name }} @if (!$runnableSourceKeys->contains($source->key)) ({{ __('not yet integrated') }}) @endif
</option>
@endforeach
</select>
<x-secondary-button type="submit">{{ __('Run') }}</x-secondary-button>
</form>
@endif
<form method="POST" action="{{ route('investigations.targets.destroy', [$investigation, $target]) }}" onsubmit="return confirm('{{ __('Delete this target and its findings?') }}');">
@csrf
@method('DELETE')
<button type="submit" class="text-xs text-red-600 dark:text-red-400 hover:underline">{{ __('Remove') }}</button>
</form>
</div>
@endif
</div>
@if ($target->findings->isNotEmpty())
<ul class="mt-3 space-y-2">
@foreach ($target->findings->sortByDesc('id') as $finding)
<li class="text-sm bg-gray-50 dark:bg-gray-900 rounded-md p-3">
<div class="flex justify-between items-center">
<span class="font-medium">{{ $finding->source->name }}</span>
<span class="text-xs uppercase tracking-wide
{{ match($finding->status) {
'completed' => 'text-green-600 dark:text-green-400',
'failed' => 'text-red-600 dark:text-red-400',
default => 'text-gray-500 dark:text-gray-400',
} }}">
{{ $finding->status }}
</span>
</div>
@if ($finding->summary)
<p class="text-gray-700 dark:text-gray-300 mt-1">{{ $finding->summary }}</p>
@endif
@if ($finding->error)
<p class="text-red-600 dark:text-red-400 mt-1">{{ $finding->error }}</p>
@endif
@if ($finding->status === 'completed' && !empty($finding->raw_payload['matches']))
<ul class="mt-2 space-y-1">
@foreach ($finding->raw_payload['matches'] as $match)
<li>
<a href="{{ $match['url'] }}" target="_blank" rel="noopener" class="text-indigo-600 dark:text-indigo-400 hover:underline">
{{ $match['name'] }}
</a>
</li>
@endforeach
</ul>
@endif
@if ($finding->status === 'completed')
@foreach (($finding->raw_payload ?? []) as $field => $items)
@continue($field === 'matches' || !is_array($items) || empty($items) || !is_string($items[0] ?? null))
<details class="mt-2">
<summary class="cursor-pointer text-gray-600 dark:text-gray-400">
{{ ucfirst($field) }} ({{ count($items) }})
</summary>
<ul class="mt-1 ml-4 list-disc space-y-0.5">
@foreach (array_slice($items, 0, 50) as $item)
<li class="text-gray-700 dark:text-gray-300">{{ $item }}</li>
@endforeach
</ul>
@if (count($items) > 50)
<p class="text-xs text-gray-500 dark:text-gray-400 ml-4">{{ __('+ :count more', ['count' => count($items) - 50]) }}</p>
@endif
</details>
@endforeach
@endif
</li>
@endforeach
</ul>
@endif
</div>
@empty
<p class="text-gray-500 dark:text-gray-400">{{ __('No targets yet.') }}</p>
@endforelse
@if ($canEdit)
<form method="POST" action="{{ route('investigations.targets.store', $investigation) }}" class="mt-6 pt-6 border-t border-gray-200 dark:border-gray-700 flex flex-wrap items-end gap-3">
@csrf
<div>
<x-input-label for="type" :value="__('Type')" />
<select id="type" name="type" class="mt-1 text-sm border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 rounded-md">
<option value="username">username</option>
<option value="domain">domain</option>
<option value="email">email</option>
<option value="ip">ip</option>
<option value="person">person</option>
<option value="org">org</option>
</select>
</div>
<div class="flex-1 min-w-[12rem]">
<x-input-label for="value" :value="__('Value')" />
<x-text-input id="value" name="value" type="text" class="mt-1 block w-full" required />
</div>
<x-primary-button type="submit">{{ __('Add target') }}</x-primary-button>
</form>
@endif
</div>
</div>
</div>
</x-app-layout>