generated from thegrind/laravel-dockerized
114 lines
6.2 KiB
PHP
114 lines
6.2 KiB
PHP
<div class="max-w-4xl mx-auto py-12">
|
|
<x-card class="space-y-6 p-6">
|
|
<flux:heading size="lg">Authentication Tokens</flux:heading>
|
|
<flux:subheading>
|
|
Manage your active authentication tokens for different applications.
|
|
</flux:subheading>
|
|
|
|
@if($this->tokens->isEmpty())
|
|
<div class="text-center py-12">
|
|
<flux:icon.shield-check variant="outline" class="mx-auto h-12 w-12 text-zinc-400" />
|
|
<flux:heading size="md" class="mt-4">No tokens</flux:heading>
|
|
<flux:subheading class="mt-2">
|
|
You haven't authorized any applications yet.
|
|
</flux:subheading>
|
|
</div>
|
|
@else
|
|
<div class="space-y-6">
|
|
@foreach($this->tokens as $appName => $appTokens)
|
|
<div class="space-y-3" x-data="{ expanded: false }"
|
|
wire:key="app-{{ $appTokens->first()->application_id }}">
|
|
<div class="flex items-center space-x-3 cursor-pointer hover:bg-zinc-50 dark:hover:bg-zinc-800/50 p-2 rounded-lg transition-colors"
|
|
x-on:click="expanded = !expanded">
|
|
<div class="flex-shrink-0">
|
|
@if($appTokens->first()->application->icon)
|
|
<img class="h-8 w-8 rounded-lg object-cover"
|
|
src="{{ $appTokens->first()->application->getIconUrl() }}" alt="{{ $appName }}"
|
|
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
|
<div class="h-8 w-8 rounded-lg bg-zinc-100 dark:bg-zinc-700 flex items-center justify-center"
|
|
style="display: none;">
|
|
<flux:icon.computer-desktop class="h-5 w-5 text-zinc-500" />
|
|
</div>
|
|
@else
|
|
<div class="h-8 w-8 rounded-lg bg-zinc-100 dark:bg-zinc-700 flex items-center justify-center">
|
|
<flux:icon.computer-desktop class="h-5 w-5 text-zinc-500" />
|
|
</div>
|
|
@endif
|
|
</div>
|
|
<div class="flex-1">
|
|
<flux:heading size="sm">{{ $appName }}</flux:heading>
|
|
<flux:subheading size="xs">{{ $appTokens->count() }} {{ $appTokens->count() === 1 ? 'token' :
|
|
'tokens' }}</flux:subheading>
|
|
</div>
|
|
<div class="flex-shrink-0">
|
|
<flux:icon.chevron-down class="h-5 w-5 text-zinc-400 transition-transform duration-200"
|
|
x-bind:class="expanded ? 'rotate-180' : ''" />
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="ml-11 space-y-2" x-show="expanded" x-transition:enter="transition ease-out duration-200"
|
|
x-transition:enter-start="opacity-0 transform -translate-y-2"
|
|
x-transition:enter-end="opacity-100 transform translate-y-0"
|
|
x-transition:leave="transition ease-in duration-150"
|
|
x-transition:leave-start="opacity-100 transform translate-y-0"
|
|
x-transition:leave-end="opacity-0 transform -translate-y-2">
|
|
@foreach($appTokens as $token)
|
|
<x-card class="p-4" wire:key="token-{{ $token->id }}">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex-1 min-w-0">
|
|
<div class="space-y-1">
|
|
<flux:subheading size="xs">
|
|
<flux:icon.calendar class="inline h-3 w-3 mr-1" />
|
|
Issued: {{ $token->issued_at->format('M j, Y \a\t g:i A') }}
|
|
</flux:subheading>
|
|
@if($token->expires_at)
|
|
<flux:subheading size="xs">
|
|
<flux:icon.clock class="inline h-3 w-3 mr-1" />
|
|
Expires: {{ $token->expires_at->format('M j, Y \a\t g:i A') }}
|
|
</flux:subheading>
|
|
@endif
|
|
@if($token->ip)
|
|
<flux:subheading size="xs">
|
|
<flux:icon.globe-alt class="inline h-3 w-3 mr-1" />
|
|
IP: {{ $token->ip }}
|
|
</flux:subheading>
|
|
@endif
|
|
@if($token->user_agent)
|
|
<flux:subheading size="xs" class="truncate">
|
|
<flux:icon.device-phone-mobile class="inline h-3 w-3 mr-1" />
|
|
<span title="{{ $token->user_agent }}">
|
|
{{ strlen($token->user_agent) > 60 ? substr($token->user_agent, 0, 60) .
|
|
'...' :
|
|
$token->user_agent }}
|
|
</span>
|
|
</flux:subheading>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
<div class="flex-shrink-0 ml-4">
|
|
<flux:button wire:click="revokeToken({{ $token->id }})" icon="trash"
|
|
wire:confirm="Are you sure you want to revoke this token? The application will need to be re-authorized."
|
|
variant="danger" size="sm">
|
|
Revoke
|
|
</flux:button>
|
|
</div>
|
|
</div>
|
|
</x-card>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</x-card>
|
|
|
|
@script
|
|
<script>
|
|
$wire.on('token-revoked', () => {
|
|
// You can add a toast notification here if you have one
|
|
console.log('Token revoked successfully');
|
|
});
|
|
</script>
|
|
@endscript
|
|
</div> |