Skip to content

Commit 3a13d3f

Browse files
committed
Ugh, redoing V1 tokens as controller
1 parent 42420dc commit 3a13d3f

7 files changed

Lines changed: 100 additions & 128 deletions

File tree

app/Http/Controllers/ApiAccessController.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,71 @@ public function destroy(Request $request, int $id): RedirectResponse
127127
->with('status', __('API token has been removed.'));
128128
}
129129

130+
// ---- v1 (Sanctum) personal access tokens ----
131+
132+
public function storeV1(Request $request): JsonResponse
133+
{
134+
$validated = $request->validate([
135+
'token_name' => 'required|string|max:255',
136+
'expires_in' => 'nullable|integer|min:1',
137+
]);
138+
139+
$user = $request->user();
140+
$expiresAt = empty($validated['expires_in'])
141+
? null
142+
: now()->addDays((int) $validated['expires_in']);
143+
144+
$token = $user->createToken($validated['token_name'], ['*'], $expiresAt);
145+
146+
return response()->json([
147+
'token' => $token->plainTextToken,
148+
'token_id' => $token->accessToken->id,
149+
'token_name' => $token->accessToken->name,
150+
'created_at' => __('Just now'),
151+
'expires_at' => $expiresAt ? $expiresAt->diffForHumans() : __('Never'),
152+
], 201);
153+
}
154+
155+
public function renewV1(Request $request, int $id): JsonResponse
156+
{
157+
$validated = $request->validate([
158+
'extend_days' => 'required|integer|min:0',
159+
]);
160+
161+
$token = $this->v1TokenOwnedByUser($request, $id);
162+
163+
// 0 days means the token never expires
164+
$token->expires_at = (int) $validated['extend_days'] === 0
165+
? null
166+
: now()->addDays((int) $validated['extend_days']);
167+
$token->save();
168+
169+
return response()->json([
170+
'expires_at' => $token->expires_at ? $token->expires_at->diffForHumans() : __('Never'),
171+
]);
172+
}
173+
174+
public function destroyV1(Request $request, int $id): JsonResponse
175+
{
176+
$this->v1TokenOwnedByUser($request, $id)->delete();
177+
178+
return response()->json(['status' => 'ok']);
179+
}
180+
130181
private function tokenOwnedByUser(Request $request, int $id): ApiToken
131182
{
132183
return ApiToken::query()
133184
->where('id', $id)
134185
->where('user_id', $request->user()->user_id)
135186
->firstOrFail();
136187
}
188+
189+
private function v1TokenOwnedByUser(Request $request, int $id): PersonalAccessToken
190+
{
191+
return PersonalAccessToken::query()
192+
->where('id', $id)
193+
->where('tokenable_type', User::class)
194+
->where('tokenable_id', $request->user()->user_id)
195+
->firstOrFail();
196+
}
137197
}

html/ajax_form.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@
5959
'show-alert-transport' => 'includes/html/forms/show-alert-transport.inc.php',
6060
'show-transport-group' => 'includes/html/forms/show-transport-group.inc.php',
6161
'storage-update' => 'includes/html/forms/storage-update.inc.php',
62-
'v1-token-item-create' => 'includes/html/forms/v1-token-item-create.inc.php',
63-
'v1-token-item-remove' => 'includes/html/forms/v1-token-item-remove.inc.php',
64-
'v1-token-item-renew' => 'includes/html/forms/v1-token-item-renew.inc.php',
6562
'transport-groups' => 'includes/html/forms/transport-groups.inc.php',
6663
'update-ifalias' => 'includes/html/forms/update-ifalias.inc.php',
6764
'update-ifspeed' => 'includes/html/forms/update-ifspeed.inc.php',

includes/html/forms/v1-token-item-create.inc.php

Lines changed: 0 additions & 38 deletions
This file was deleted.

includes/html/forms/v1-token-item-remove.inc.php

Lines changed: 0 additions & 26 deletions
This file was deleted.

includes/html/forms/v1-token-item-renew.inc.php

Lines changed: 0 additions & 37 deletions
This file was deleted.

resources/views/user/api-access.blade.php

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -390,10 +390,15 @@ function setDescriptionView($cell, raw) {
390390
$('#remove_token_form').attr('action', baseUrl + '/' + token_id);
391391
});
392392
393-
var v1FormUrl = "{{ url('ajax_form.php') }}";
394-
395-
function v1Post(type, data) {
396-
return $.post(v1FormUrl, $.extend({ type: type }, data), null, 'json');
393+
function v1FailMessage(xhr, fallback) {
394+
var j = xhr.responseJSON;
395+
if (j && j.errors) {
396+
return Object.values(j.errors)[0][0];
397+
}
398+
if (j && j.message) {
399+
return j.message;
400+
}
401+
return fallback;
397402
}
398403
399404
function v1ToastError(msg) {
@@ -411,12 +416,16 @@ function v1EscapeHtml(s) {
411416
$('#v1-create-token-form').on('submit', function (e) {
412417
e.preventDefault();
413418
var $form = $(this);
414-
v1Post('v1-token-item-create', {
415-
token_name: $form.find('[name=token_name]').val(),
416-
expires_in: $form.find('[name=expires_in]').val()
419+
$.ajax({
420+
type: 'POST',
421+
url: baseUrl + '/v1',
422+
contentType: 'application/json',
423+
data: JSON.stringify({
424+
token_name: $form.find('[name=token_name]').val(),
425+
expires_in: $form.find('[name=expires_in]').val()
426+
}),
427+
dataType: 'json'
417428
}).done(function (data) {
418-
if (data.status !== 'ok') { v1ToastError(data.message || 'Error'); return; }
419-
420429
$('#v1-tokens-empty').remove();
421430
$('#v1-tokens-table tbody').append(
422431
'<tr id="v1-token-row-' + data.token_id + '">' +
@@ -433,8 +442,8 @@ function v1EscapeHtml(s) {
433442
$('#v1-token-plain-alert').removeClass('hidden');
434443
$('#v1-create-token').modal('hide');
435444
$form[0].reset();
436-
}).fail(function () {
437-
v1ToastError(@json(__('Could not create token.')));
445+
}).fail(function (xhr) {
446+
v1ToastError(v1FailMessage(xhr, @json(__('Could not create token.'))));
438447
});
439448
});
440449
@@ -446,15 +455,19 @@ function v1EscapeHtml(s) {
446455
e.preventDefault();
447456
var $form = $(this);
448457
var tokenId = $form.find('[name=v1_token_id]').val();
449-
v1Post('v1-token-item-renew', {
450-
v1_token_id: tokenId,
451-
extend_days: $form.find('[name=extend_days]').val()
458+
$.ajax({
459+
type: 'PATCH',
460+
url: baseUrl + '/v1/' + tokenId + '/renew',
461+
contentType: 'application/json',
462+
data: JSON.stringify({
463+
extend_days: $form.find('[name=extend_days]').val()
464+
}),
465+
dataType: 'json'
452466
}).done(function (data) {
453-
if (data.status !== 'ok') { v1ToastError(data.message || 'Error'); return; }
454467
$('#v1-token-row-' + tokenId).find('.v1-token-expires').text(data.expires_at);
455468
$('#v1-renew-token').modal('hide');
456-
}).fail(function () {
457-
v1ToastError(@json(__('Could not renew token.')));
469+
}).fail(function (xhr) {
470+
v1ToastError(v1FailMessage(xhr, @json(__('Could not renew token.'))));
458471
});
459472
});
460473
@@ -466,18 +479,18 @@ function v1EscapeHtml(s) {
466479
e.preventDefault();
467480
var $form = $(this);
468481
var tokenId = $form.find('[name=v1_token_id]').val();
469-
v1Post('v1-token-item-remove', {
470-
v1_token_id: tokenId,
471-
confirm: 'yes'
472-
}).done(function (data) {
473-
if (data.status !== 'ok') { v1ToastError(data.message || 'Error'); return; }
482+
$.ajax({
483+
type: 'DELETE',
484+
url: baseUrl + '/v1/' + tokenId,
485+
dataType: 'json'
486+
}).done(function () {
474487
$('#v1-token-row-' + tokenId).remove();
475488
if ($('#v1-tokens-table tbody tr').length === 0) {
476489
$('#v1-tokens-table tbody').append('<tr id="v1-tokens-empty"><td colspan="6">' + @json(__('No v1 API tokens yet.')) + '</td></tr>');
477490
}
478491
$('#v1-confirm-delete').modal('hide');
479-
}).fail(function () {
480-
v1ToastError(@json(__('Could not delete token.')));
492+
}).fail(function (xhr) {
493+
v1ToastError(v1FailMessage(xhr, @json(__('Could not delete token.'))));
481494
});
482495
});
483496
})();

routes/web.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@
135135
Route::patch('api-access/{id}', [ApiAccessController::class, 'update'])->name('api-access.update')->whereNumber('id');
136136
Route::post('api-access/{id}/reset', [ApiAccessController::class, 'reset'])->name('api-access.reset')->whereNumber('id');
137137
Route::delete('api-access/{id}', [ApiAccessController::class, 'destroy'])->name('api-access.destroy')->whereNumber('id');
138+
Route::post('api-access/v1', [ApiAccessController::class, 'storeV1'])->name('api-access.v1.store');
139+
Route::patch('api-access/v1/{id}/renew', [ApiAccessController::class, 'renewV1'])->name('api-access.v1.renew')->whereNumber('id');
140+
Route::delete('api-access/v1/{id}', [ApiAccessController::class, 'destroyV1'])->name('api-access.v1.destroy')->whereNumber('id');
138141
});
139142
Route::resource('users', UserController::class);
140143
Route::prefix('users/{user}/permissions')->name('users.permissions.')->group(function (): void {

0 commit comments

Comments
 (0)