API Tokens: Updated interfaces to return to correct location

Since management of API tokens can be accessed via two routes, this adds
tracking and handling to reutrn the user to the correct place.
This commit is contained in:
Dan Brown 2023-10-19 11:31:45 +01:00
parent f9422dff18
commit 12946414b0
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
9 changed files with 67 additions and 29 deletions

@ -52,4 +52,12 @@ class ApiToken extends Model implements Loggable
{
return "({$this->id}) {$this->name}; User: {$this->user->logDescriptor()}";
}
/**
* Get the URL for managing this token.
*/
public function getUrl(string $path = ''): string
{
return url("/api-tokens/{$this->user_id}/{$this->id}/" . trim($path, '/'));
}
}

@ -14,16 +14,17 @@ class UserApiTokenController extends Controller
/**
* Show the form to create a new API token.
*/
public function create(int $userId)
public function create(Request $request, int $userId)
{
// Ensure user is has access-api permission and is the current user or has permission to manage the current user.
$this->checkPermission('access-api');
$this->checkPermissionOrCurrentUser('users-manage', $userId);
$this->updateContext($request);
$user = User::query()->findOrFail($userId);
return view('users.api-tokens.create', [
'user' => $user,
'back' => $this->getRedirectPath($user),
]);
}
@ -60,14 +61,16 @@ class UserApiTokenController extends Controller
session()->flash('api-token-secret:' . $token->id, $secret);
$this->logActivity(ActivityType::API_TOKEN_CREATE, $token);
return redirect($user->getEditUrl('/api-tokens/' . $token->id));
return redirect($token->getUrl());
}
/**
* Show the details for a user API token, with access to edit.
*/
public function edit(int $userId, int $tokenId)
public function edit(Request $request, int $userId, int $tokenId)
{
$this->updateContext($request);
[$user, $token] = $this->checkPermissionAndFetchUserToken($userId, $tokenId);
$secret = session()->pull('api-token-secret:' . $token->id, null);
@ -76,6 +79,7 @@ class UserApiTokenController extends Controller
'token' => $token,
'model' => $token,
'secret' => $secret,
'back' => $this->getRedirectPath($user),
]);
}
@ -97,7 +101,7 @@ class UserApiTokenController extends Controller
$this->logActivity(ActivityType::API_TOKEN_UPDATE, $token);
return redirect($user->getEditUrl('/api-tokens/' . $token->id));
return redirect($token->getUrl());
}
/**
@ -123,7 +127,7 @@ class UserApiTokenController extends Controller
$this->logActivity(ActivityType::API_TOKEN_DELETE, $token);
return redirect($user->getEditUrl('#api_tokens'));
return redirect($this->getRedirectPath($user));
}
/**
@ -142,4 +146,30 @@ class UserApiTokenController extends Controller
return [$user, $token];
}
/**
* Update the context for where the user is coming from to manage API tokens.
* (Track of location for correct return redirects)
*/
protected function updateContext(Request $request): void
{
$context = $request->query('context');
if ($context) {
session()->put('api-token-context', $context);
}
}
/**
* Get the redirect path for the current api token editing session.
* Attempts to recall the context of where the user is editing from.
*/
protected function getRedirectPath(User $relatedUser): string
{
$context = session()->get('api-token-context');
if ($context === 'settings') {
return $relatedUser->getEditUrl('#api_tokens');
}
return url('/my-account/auth#api_tokens');
}
}

@ -82,6 +82,6 @@
@endif
@if(userCan('access-api'))
@include('users.api-tokens.parts.list', ['user' => user()])
@include('users.api-tokens.parts.list', ['user' => user(), 'context' => 'my-account'])
@endif
@stop

@ -7,8 +7,8 @@
<main class="card content-wrap auto-height">
<h1 class="list-heading">{{ trans('settings.user_api_token_create') }}</h1>
<form action="{{ $user->getEditUrl('/create-api-token') }}" method="post">
{!! csrf_field() !!}
<form action="{{ url('/api-tokens/' . $user->id . '/create') }}" method="post">
{{ csrf_field() }}
<div class="setting-list">
@include('users.api-tokens.parts.form')
@ -21,7 +21,7 @@
</div>
<div class="form-group text-right">
<a href="{{ $user->getEditUrl('#api_tokens') }}" class="button outline">{{ trans('common.cancel') }}</a>
<a href="{{ $back }}" class="button outline">{{ trans('common.cancel') }}</a>
<button class="button" type="submit">{{ trans('common.save') }}</button>
</div>

@ -11,11 +11,11 @@
<div class="grid half">
<p class="text-neg"><strong>{{ trans('settings.user_api_token_delete_confirm') }}</strong></p>
<div>
<form action="{{ $user->getEditUrl('/api-tokens/' . $token->id) }}" method="POST" class="text-right">
{!! csrf_field() !!}
{!! method_field('delete') !!}
<form action="{{ $token->getUrl() }}" method="POST" class="text-right">
{{ csrf_field() }}
{{ method_field('delete') }}
<a href="{{ $user->getEditUrl('/api-tokens/' . $token->id) }}" class="button outline">{{ trans('common.cancel') }}</a>
<a href="{{ $token->getUrl() }}" class="button outline">{{ trans('common.cancel') }}</a>
<button type="submit" class="button">{{ trans('common.confirm') }}</button>
</form>
</div>

@ -7,9 +7,9 @@
<main class="card content-wrap auto-height">
<h1 class="list-heading">{{ trans('settings.user_api_token') }}</h1>
<form action="{{ $user->getEditUrl('/api-tokens/' . $token->id) }}" method="post">
{!! method_field('put') !!}
{!! csrf_field() !!}
<form action="{{ $token->getUrl() }}" method="post">
{{ method_field('put') }}
{{ csrf_field() }}
<div class="setting-list">
@ -52,8 +52,8 @@
</div>
<div class="form-group text-right">
<a href="{{ $user->getEditUrl('#api_tokens') }}" class="button outline">{{ trans('common.back') }}</a>
<a href="{{ $user->getEditUrl('/api-tokens/' . $token->id . '/delete') }}" class="button outline">{{ trans('settings.user_api_token_delete') }}</a>
<a href="{{ $back }}" class="button outline">{{ trans('common.back') }}</a>
<a href="{{ $token->getUrl('/delete') }}" class="button outline">{{ trans('settings.user_api_token_delete') }}</a>
<button class="button" type="submit">{{ trans('common.save') }}</button>
</div>
</div>

@ -4,7 +4,7 @@
<div class="text-right pt-xs">
@if(userCan('access-api'))
<a href="{{ url('/api/docs') }}" class="button outline">{{ trans('settings.users_api_tokens_docs') }}</a>
<a href="{{ $user->getEditUrl('/create-api-token') }}" class="button outline">{{ trans('settings.users_api_tokens_create') }}</a>
<a href="{{ url('/api-tokens/' . $user->id . '/create?context=' . $context) }}" class="button outline">{{ trans('settings.users_api_tokens_create') }}</a>
@endif
</div>
</div>
@ -14,7 +14,7 @@
@foreach($user->apiTokens as $token)
<div class="item-list-row flex-container-row items-center wrap py-xs gap-x-m">
<div class="flex px-m py-xs min-width-m">
<a href="{{ $user->getEditUrl('/api-tokens/' . $token->id) }}">{{ $token->name }}</a> <br>
<a href="{{ $token->getUrl("?context={$context}") }}">{{ $token->name }}</a> <br>
<span class="small text-muted italic">{{ $token->token_id }}</span>
</div>
<div class="flex flex-container-row items-center min-width-m">
@ -23,7 +23,7 @@
{{ $token->expires_at->format('Y-m-d') ?? '' }}
</div>
<div class="flex px-m py-xs text-right">
<a class="button outline small" href="{{ $user->getEditUrl('/api-tokens/' . $token->id) }}">{{ trans('common.edit') }}</a>
<a class="button outline small" href="{{ $token->getUrl("?context={$context}") }}">{{ trans('common.edit') }}</a>
</div>
</div>
</div>

@ -100,7 +100,7 @@
</section>
@endif
@include('users.api-tokens.parts.list', ['user' => $user])
@include('users.api-tokens.parts.list', ['user' => $user, 'context' => 'settings'])
</div>
@stop

@ -251,12 +251,12 @@ Route::middleware('auth')->group(function () {
Route::patch('/preferences/update-code-language-favourite', [UserControllers\UserPreferencesController::class, 'updateCodeLanguageFavourite']);
// User API Tokens
Route::get('/settings/users/{userId}/create-api-token', [UserApiTokenController::class, 'create']);
Route::post('/settings/users/{userId}/create-api-token', [UserApiTokenController::class, 'store']);
Route::get('/settings/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'edit']);
Route::put('/settings/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'update']);
Route::get('/settings/users/{userId}/api-tokens/{tokenId}/delete', [UserApiTokenController::class, 'delete']);
Route::delete('/settings/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'destroy']);
Route::get('/api-tokens/{userId}/create', [UserApiTokenController::class, 'create']);
Route::post('/api-tokens/{userId}/create', [UserApiTokenController::class, 'store']);
Route::get('/api-tokens/{userId}/{tokenId}', [UserApiTokenController::class, 'edit']);
Route::put('/api-tokens/{userId}/{tokenId}', [UserApiTokenController::class, 'update']);
Route::get('/api-tokens/{userId}/{tokenId}/delete', [UserApiTokenController::class, 'delete']);
Route::delete('/api-tokens/{userId}/{tokenId}', [UserApiTokenController::class, 'destroy']);
// Roles
Route::get('/settings/roles', [UserControllers\RoleController::class, 'index']);