Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions config/permissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,18 @@
'flag' => 'api.settings',
'parent_flag' => 'settings.options',
],
[
'name' => 'Sanctum Token',
'flag' => 'api.sanctum-token.index',
],
[
'name' => 'Create',
'flag' => 'api.sanctum-token.create',
'parent_flag' => 'api.sanctum-token.index',
],
[
'name' => 'Delete',
'flag' => 'api.sanctum-token.destroy',
'parent_flag' => 'api.sanctum-token.index',
],
];
8 changes: 8 additions & 0 deletions resources/lang/en/sanctum-token.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

return [
'name' => 'Sanctum Token',
'create' => 'New Sanctum Token',
'abilities' => 'Abilities',
'last_used_at' => 'Last used at',
];
30 changes: 30 additions & 0 deletions resources/views/table.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@extends(BaseHelper::getAdminMasterLayoutTemplate())

@section('content')
@if(session()->has('plainTextToken'))
<x-core::alert
type="success"
:title="__('This is your new personal access token, this token only show 1 time, make sure you have copied it.')"
>
<div class="d-flex align-items-center gap-1 mt-2">
<code>{{ session('plainTextToken') }}</code>

<a
href="javascript:void(0);"
data-bb-toggle="clipboard"
data-clipboard-action="copy"
data-clipboard-text="{{ session('plainTextToken') }}"
data-clipboard-message="{{ trans('core/table::table.copied') }}"
data-bs-toggle="tooltip"
title="{{ trans('core/table::table.copy') }}"
class="text-muted text-center text-decoration-none"
>
<span class="sr-only">{{ trans('core/table::table.copy') }}</span>
<x-core::icon name="ti ti-clipboard" />
</a>
</div>
</x-core::alert>
@endif

@include('core/table::base-table')
@stop
27 changes: 14 additions & 13 deletions routes/web.php
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
<?php

use Botble\Api\Http\Controllers\ApiController;
use Botble\Api\Http\Controllers\SanctumTokenController;
use Botble\Base\Facades\BaseHelper;
use Illuminate\Support\Facades\Route;

Route::group(['namespace' => 'Botble\Api\Http\Controllers', 'middleware' => ['web', 'core']], function () {
Route::group(['prefix' => BaseHelper::getAdminPrefix(), 'middleware' => 'auth'], function () {
Route::group(['prefix' => 'settings/api'], function () {
Route::get('', [
'as' => 'api.settings',
'uses' => 'ApiController@settings',
]);
Route::prefix(BaseHelper::getAdminPrefix())
->middleware(['core', 'web', 'auth'])
->name('api.')
->group(function () {
Route::prefix('sanctum-token')->name('sanctum-token.')->group(function () {
Route::resource('/', SanctumTokenController::class)
->parameters(['' => 'sanctum-token'])
->except('edit', 'update', 'show');
});

Route::post('', [
'as' => 'api.settings.update',
'uses' => 'ApiController@storeSettings',
'permission' => 'api.settings',
]);
Route::group(['prefix' => 'settings/api', 'permission' => 'api.settings'], function () {
Route::get('/', [ApiController::class, 'edit'])->name('settings');
Route::post('/', [ApiController::class, 'update'])->name('settings.update');
});
});
});
20 changes: 20 additions & 0 deletions src/Forms/SanctumTokenForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Botble\Api\Forms;

use Botble\Api\Http\Requests\StoreSanctumTokenRequest;
use Botble\Api\Models\PersonalAccessToken;
use Botble\Base\Forms\FieldOptions\TextFieldOption;
use Botble\Base\Forms\Fields\TextField;
use Botble\Base\Forms\FormAbstract;

class SanctumTokenForm extends FormAbstract
{
public function buildForm(): void
{
$this
->setupModel(new PersonalAccessToken())
->setValidatorClass(StoreSanctumTokenRequest::class)
->add('name', TextField::class, TextFieldOption::make()->label(__('core/base::tables.name'))->toArray());
}
}
9 changes: 4 additions & 5 deletions src/Http/Controllers/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@
use Botble\Base\Facades\PageTitle;
use Botble\Base\Http\Controllers\BaseController;
use Botble\Base\Http\Responses\BaseHttpResponse;
use Botble\Base\Supports\Breadcrumb;

class ApiController extends BaseController
{
public function settings()
public function edit()
{
PageTitle::setTitle(trans('packages/api::api.settings'));

Assets::addScriptsDirectly('vendor/core/core/setting/js/setting.js');
Assets::addStylesDirectly('vendor/core/core/setting/css/setting.css');
Assets::addScriptsDirectly('vendor/core/core/setting/js/setting.js')
->addStylesDirectly('vendor/core/core/setting/css/setting.css');

if (version_compare('7.0.0', get_core_version(), '>')) {
return view('packages/api::settings-v6');
Expand All @@ -29,7 +28,7 @@ public function settings()
return view('packages/api::settings');
}

public function storeSettings(ApiSettingRequest $request, BaseHttpResponse $response)
public function update(ApiSettingRequest $request, BaseHttpResponse $response)
{
$this->saveSettings($request->validated());

Expand Down
60 changes: 60 additions & 0 deletions src/Http/Controllers/SanctumTokenController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Botble\Api\Http\Controllers;

use Botble\Api\Forms\SanctumTokenForm;
use Botble\Api\Http\Requests\StoreSanctumTokenRequest;
use Botble\Api\Models\PersonalAccessToken;
use Botble\Api\Tables\SanctumTokenTable;
use Botble\Base\Facades\PageTitle;
use Botble\Base\Http\Controllers\BaseController;
use Botble\Base\Http\Responses\BaseHttpResponse;
use Exception;
use Illuminate\Contracts\View\View;
use Illuminate\Http\JsonResponse;

class SanctumTokenController extends BaseController
{
public function index(SanctumTokenTable $sanctumTokenTable): JsonResponse|View
{
PageTitle::setTitle(trans('packages/api::sanctum-token.name'));

return $sanctumTokenTable->renderTable();
}

public function create()
{
PageTitle::setTitle(trans('packages/api::sanctum-token.create'));

return SanctumTokenForm::create()->renderForm();
}

public function store(StoreSanctumTokenRequest $request): BaseHttpResponse
{
$accessToken = $request->user()->createToken($request->input('name'));

session()->flash('plainTextToken', $accessToken->plainTextToken);

return $this
->httpResponse()
->setPreviousUrl(route('api.sanctum-token.index'))
->setNextUrl(route('api.sanctum-token.index'))
->withCreatedSuccessMessage();
}

public function destroy(string $id): BaseHttpResponse
{
try {
PersonalAccessToken::findOrFail($id)->delete();

return $this
->httpResponse()
->setMessage(trans('core/base::notices.delete_success_message'));
} catch (Exception $exception) {
return $this
->httpResponse()
->setError()
->setMessage($exception->getMessage());
}
}
}
16 changes: 16 additions & 0 deletions src/Http/Requests/StoreSanctumTokenRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Botble\Api\Http\Requests;

use Botble\Support\Http\Requests\Request;

class StoreSanctumTokenRequest extends Request
{
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'abilities' => ['nullable', 'array'],
];
}
}
16 changes: 16 additions & 0 deletions src/Models/PersonalAccessToken.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Botble\Api\Models;

use Botble\Base\Contracts\BaseModel;
use Botble\Base\Models\Concerns\HasBaseEloquentBuilder;
use Botble\Base\Models\Concerns\HasMetadata;
use Botble\Base\Models\Concerns\HasUuidsOrIntegerIds;
use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken;

class PersonalAccessToken extends SanctumPersonalAccessToken implements BaseModel
{
use HasMetadata;
use HasUuidsOrIntegerIds;
use HasBaseEloquentBuilder;
}
20 changes: 16 additions & 4 deletions src/Providers/ApiServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Botble\Api\Facades\ApiHelper;
use Botble\Api\Http\Middleware\ForceJsonResponseMiddleware;
use Botble\Api\Models\PersonalAccessToken;
use Botble\Base\Facades\DashboardMenu;
use Botble\Base\Facades\PanelSectionManager;
use Botble\Base\PanelSections\PanelSectionItem;
Expand All @@ -12,9 +13,7 @@
use Botble\Setting\PanelSections\SettingCommonPanelSection;
use Illuminate\Foundation\AliasLoader;
use Illuminate\Routing\Events\RouteMatched;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use ReflectionClass;
use Laravel\Sanctum\Sanctum;

class ApiServiceProvider extends ServiceProvider
{
Expand All @@ -41,6 +40,19 @@ public function boot(): void
$this->loadRoutes(['api']);
}

Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);

DashboardMenu::default()->beforeRetrieving(function () {
DashboardMenu::make()
->registerItem([
'id' => 'cms-packages-api-sanctum-token',
'name' => trans('packages/api::sanctum-token.name'),
'icon' => 'ti ti-key',
'url' => route('api.sanctum-token.index'),
'permissions' => ['api.sanctum-token.index'],
]);
});

$this->app['events']->listen(RouteMatched::class, function () {
if (ApiHelper::enabled()) {
$this->app['router']->pushMiddlewareToGroup('api', ForceJsonResponseMiddleware::class);
Expand Down Expand Up @@ -81,7 +93,7 @@ public function boot(): void
});
}

protected function getPath(string $path = null): string
protected function getPath(string|null $path = null): string
{
return __DIR__ . '/../..' . ($path ? '/' . ltrim($path, '/') : '');
}
Expand Down
44 changes: 44 additions & 0 deletions src/Tables/SanctumTokenTable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Botble\Api\Tables;

use Botble\Api\Models\PersonalAccessToken;
use Botble\Table\Abstracts\TableAbstract;
use Botble\Table\Actions\DeleteAction;
use Botble\Table\BulkActions\DeleteBulkAction;
use Botble\Table\Columns\Column;
use Botble\Table\Columns\CreatedAtColumn;
use Botble\Table\Columns\DateTimeColumn;
use Botble\Table\Columns\IdColumn;
use Botble\Table\Columns\NameColumn;
use Botble\Table\HeaderActions\CreateHeaderAction;
use Illuminate\Database\Eloquent\Builder;

class SanctumTokenTable extends TableAbstract
{
public function setup(): void
{
$this
->setView('packages/api::table')
->model(PersonalAccessToken::class)
->addHeaderAction(CreateHeaderAction::make()->route('api.sanctum-token.create'))
->addAction(DeleteAction::make()->route('api.sanctum-token.destroy'))
->addColumns([
IdColumn::make(),
NameColumn::make(),
Column::make('abilities')
->label(__('packages/api::sanctum-token.abilities')),
DateTimeColumn::make('last_used_at')
->label(__('packages/api::sanctum-token.last_used_at')),
CreatedAtColumn::make(),
])
->addBulkAction(DeleteBulkAction::make())
->queryUsing(fn (Builder $query) => $query->select([
'id',
'name',
'abilities',
'last_used_at',
'created_at',
]));
}
}