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

View File

@ -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, '/'));
}
}

View File

@ -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');
}
}

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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']);