Compare commits
9 changed files with 20 additions and 196 deletions
|
|
@ -254,7 +254,7 @@ class PasskeysController extends Controller
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$passkey = Passkey::firstWhere('passkey_id', Base64UrlSafe::encodeUnpadded($publicKeyCredential->rawId));
|
$passkey = Passkey::firstWhere('passkey_id', $publicKeyCredential->id);
|
||||||
if (! $passkey) {
|
if (! $passkey) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
|
|
@ -1,137 +0,0 @@
|
||||||
@layer components {
|
|
||||||
.token-list-wrapper {
|
|
||||||
margin-block-start: 1em;
|
|
||||||
border: 1px solid var(--clr-border);
|
|
||||||
border-radius: 16px;
|
|
||||||
overflow: auto hidden;
|
|
||||||
background: light-dark(
|
|
||||||
oklch(99% 0.02 var(--primary-hue)),
|
|
||||||
oklch(22% 0.05 var(--primary-hue))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.token-list {
|
|
||||||
width: 100%;
|
|
||||||
min-width: 640px;
|
|
||||||
table-layout: fixed;
|
|
||||||
border-collapse: collapse;
|
|
||||||
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
text-align: left;
|
|
||||||
padding: 0.9em 1.2em;
|
|
||||||
border-bottom: 1px solid var(--clr-border);
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
font-size: 0.8em;
|
|
||||||
font-weight: 700;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.08em;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr.is-revoked {
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
th:nth-child(1),
|
|
||||||
td:nth-child(1) {
|
|
||||||
width: 31%;
|
|
||||||
}
|
|
||||||
|
|
||||||
th:nth-child(2),
|
|
||||||
td:nth-child(2) {
|
|
||||||
width: 24%;
|
|
||||||
}
|
|
||||||
|
|
||||||
th:nth-child(3),
|
|
||||||
td:nth-child(3) {
|
|
||||||
width: 15%;
|
|
||||||
}
|
|
||||||
|
|
||||||
th:nth-child(4),
|
|
||||||
td:nth-child(4) {
|
|
||||||
width: 16%;
|
|
||||||
}
|
|
||||||
|
|
||||||
th:nth-child(5),
|
|
||||||
td:nth-child(5) {
|
|
||||||
width: 14%;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr:last-child td {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.scope-chips {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 0.4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scope-chip {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0.2em 0.7em;
|
|
||||||
border-radius: 999px;
|
|
||||||
background: light-dark(
|
|
||||||
oklch(92% 0.05 var(--primary-hue)),
|
|
||||||
oklch(35% 0.08 var(--primary-hue))
|
|
||||||
);
|
|
||||||
font-size: 0.85em;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge,
|
|
||||||
.token-list button.revoke {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.4em;
|
|
||||||
padding: 0.3em 0.8em;
|
|
||||||
border-radius: 999px;
|
|
||||||
font-size: 0.85em;
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: 1.5;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge {
|
|
||||||
background: transparent;
|
|
||||||
border: 1px solid currentcolor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-active {
|
|
||||||
color: light-dark(oklch(35% 0.16 145deg), oklch(75% 0.16 145deg));
|
|
||||||
|
|
||||||
.dot {
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: currentcolor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-revoked {
|
|
||||||
color: var(--clr-text);
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token-list button.revoke {
|
|
||||||
background: light-dark(oklch(92% 0.15 25deg), oklch(30% 0.12 25deg));
|
|
||||||
color: light-dark(oklch(30% 0.15 25deg), oklch(92% 0.12 25deg));
|
|
||||||
border: 1px solid transparent;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 150ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token-list button.revoke:hover {
|
|
||||||
background: light-dark(oklch(80% 0.2 25deg), oklch(45% 0.18 25deg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -8,4 +8,3 @@
|
||||||
@import url('notes.css');
|
@import url('notes.css');
|
||||||
@import url('pagination.css');
|
@import url('pagination.css');
|
||||||
@import url('theme-selector.css');
|
@import url('theme-selector.css');
|
||||||
@import url('admin-tokens.css');
|
|
||||||
|
|
|
||||||
|
|
@ -18,19 +18,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
> main {
|
> main {
|
||||||
grid-column: 1/-1;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: subgrid;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
grid-column: 2/3;
|
grid-column: 2/3;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .full-bleed {
|
|
||||||
grid-column: 1/-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> footer {
|
> footer {
|
||||||
grid-column: 1/-1;
|
grid-column: 1/-1;
|
||||||
margin-block-start: 2ex;
|
margin-block-start: 2ex;
|
||||||
|
|
|
||||||
|
|
@ -7,49 +7,21 @@
|
||||||
@if($tokens->isEmpty())
|
@if($tokens->isEmpty())
|
||||||
<p>No tokens have been issued.</p>
|
<p>No tokens have been issued.</p>
|
||||||
@else
|
@else
|
||||||
<div class="full-bleed token-list-wrapper">
|
<ul>
|
||||||
<table class="token-list">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col">Client</th>
|
|
||||||
<th scope="col">Scope</th>
|
|
||||||
<th scope="col">Issued</th>
|
|
||||||
<th scope="col">Status</th>
|
|
||||||
<th scope="col">Action</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach($tokens as $token)
|
@foreach($tokens as $token)
|
||||||
<tr class="{{ $token->isRevoked ? 'is-revoked' : '' }}">
|
<li>
|
||||||
<td><a href="{{ $token->client_id }}" rel="noopener">{{ $token->client_id }}</a></td>
|
{{ $token->client_id }} — scope: {{ $token->scope }} — issued {{ $token->created_at->diffForHumans() }}
|
||||||
<td>
|
|
||||||
<span class="scope-chips">
|
|
||||||
@foreach(explode(' ', $token->scope) as $scope)
|
|
||||||
<span class="scope-chip">{{ $scope }}</span>
|
|
||||||
@endforeach
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td><time datetime="{{ $token->created_at->toIso8601String() }}" title="{{ $token->created_at }}">{{ $token->created_at->diffForHumans() }}</time></td>
|
|
||||||
<td>
|
|
||||||
@if($token->isRevoked)
|
@if($token->isRevoked)
|
||||||
<span class="badge badge-revoked">Revoked {{ $token->revoked_at->diffForHumans() }}</span>
|
— revoked {{ $token->revoked_at->diffForHumans() }}
|
||||||
@else
|
@else
|
||||||
<span class="badge badge-active"><span class="dot"></span>Active</span>
|
<form action="/admin/tokens/{{ $token->id }}/revoke" method="post">
|
||||||
@endif
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@unless($token->isRevoked)
|
|
||||||
<form action="/admin/tokens/{{ $token->id }}/revoke" method="post" onsubmit="return confirm('Revoke this token? This cannot be undone.')">
|
|
||||||
{{ csrf_field() }}
|
{{ csrf_field() }}
|
||||||
{{ method_field('PUT') }}
|
{{ method_field('PUT') }}
|
||||||
<button type="submit" class="revoke" name="revoke">Revoke</button>
|
<button type="submit" name="revoke">Revoke</button>
|
||||||
</form>
|
</form>
|
||||||
@endunless
|
@endif
|
||||||
</td>
|
</li>
|
||||||
</tr>
|
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</ul>
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
@endif
|
@endif
|
||||||
@stop
|
@stop
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue