diff --git a/config/permissions.php b/config/permissions.php index a21294e..1dfcd70 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -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', + ], ]; diff --git a/resources/lang/en/sanctum-token.php b/resources/lang/en/sanctum-token.php new file mode 100644 index 0000000..099ab0f --- /dev/null +++ b/resources/lang/en/sanctum-token.php @@ -0,0 +1,9 @@ + 'Sanctum Token', + 'create' => 'New Sanctum Token', + 'abilities' => 'Abilities', + 'last_used_at' => 'Last used at', + 'generated_message' => 'This is your new personal access token, this token only show 1 time, make sure you have copied it.', +]; diff --git a/resources/views/settings-v6.blade.php b/resources/views/settings-v6.blade.php deleted file mode 100644 index 96bceda..0000000 --- a/resources/views/settings-v6.blade.php +++ /dev/null @@ -1,25 +0,0 @@ -@extends(BaseHelper::getAdminMasterLayoutTemplate()) - -@section('content') -
- {!! Form::open(['route' => ['api.settings.update']]) !!} - - - - -
-
 
-
- -
-
- {!! Form::close() !!} -
-@endsection diff --git a/resources/views/table.blade.php b/resources/views/table.blade.php new file mode 100644 index 0000000..9748339 --- /dev/null +++ b/resources/views/table.blade.php @@ -0,0 +1,30 @@ +@extends(BaseHelper::getAdminMasterLayoutTemplate()) + +@section('content') + @if(session()->has('plainTextToken')) + +
+ {{ session('plainTextToken') }} + + + {{ trans('core/table::table.copy') }} + + +
+
+ @endif + + @include('core/table::base-table') +@stop diff --git a/routes/web.php b/routes/web.php index 44ebb43..42bf4c5 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,21 +1,21 @@ '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', - ]); +AdminHelper::registerRoutes(function () { + Route::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'); }); }); }); diff --git a/src/Forms/SanctumTokenForm.php b/src/Forms/SanctumTokenForm.php new file mode 100644 index 0000000..fb7efb8 --- /dev/null +++ b/src/Forms/SanctumTokenForm.php @@ -0,0 +1,20 @@ +setupModel(new PersonalAccessToken()) + ->setValidatorClass(StoreSanctumTokenRequest::class) + ->add('name', TextField::class, NameFieldOption::make()->toArray()); + } +} diff --git a/src/Http/Controllers/ApiController.php b/src/Http/Controllers/ApiController.php index 8caeb97..e12a2ec 100644 --- a/src/Http/Controllers/ApiController.php +++ b/src/Http/Controllers/ApiController.php @@ -4,23 +4,16 @@ use Botble\Api\Http\Requests\ApiSettingRequest; use Botble\Base\Facades\Assets; -use Botble\Base\Facades\PageTitle; -use Botble\Base\Http\Controllers\BaseController; -use Botble\Base\Http\Responses\BaseHttpResponse; -use Botble\Base\Supports\Breadcrumb; +use Botble\Setting\Http\Controllers\SettingController; -class ApiController extends BaseController +class ApiController extends SettingController { - public function settings() + public function edit() { - PageTitle::setTitle(trans('packages/api::api.settings')); + $this->pageTitle(trans('packages/api::api.settings')); - Assets::addScriptsDirectly('vendor/core/core/setting/js/setting.js'); - Assets::addStylesDirectly('vendor/core/core/setting/css/setting.css'); - - if (version_compare('7.0.0', get_core_version(), '>')) { - return view('packages/api::settings-v6'); - } + Assets::addScriptsDirectly('vendor/core/core/setting/js/setting.js') + ->addStylesDirectly('vendor/core/core/setting/css/setting.css'); $this->breadcrumb() ->add(trans('core/setting::setting.title'), route('settings.index')) @@ -29,25 +22,8 @@ public function settings() return view('packages/api::settings'); } - public function storeSettings(ApiSettingRequest $request, BaseHttpResponse $response) + public function update(ApiSettingRequest $request) { - $this->saveSettings($request->validated()); - - return $response - ->setPreviousUrl(route('api.settings')) - ->setMessage(trans('core/base::notices.update_success_message')); - } - - protected function saveSettings(array $data) - { - foreach ($data as $settingKey => $settingValue) { - if (is_array($settingValue)) { - $settingValue = json_encode(array_filter($settingValue)); - } - - setting()->set($settingKey, (string)$settingValue); - } - - setting()->save(); + return $this->performUpdate($request->validated()); } } diff --git a/src/Http/Controllers/SanctumTokenController.php b/src/Http/Controllers/SanctumTokenController.php new file mode 100644 index 0000000..98eba2e --- /dev/null +++ b/src/Http/Controllers/SanctumTokenController.php @@ -0,0 +1,48 @@ +pageTitle(trans('packages/api::sanctum-token.name')); + + return $sanctumTokenTable->renderTable(); + } + + public function create() + { + $this->pageTitle(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(PersonalAccessToken $sanctumToken): DeleteResourceAction + { + return DeleteResourceAction::make($sanctumToken); + } +} diff --git a/src/Http/Requests/ApiSettingRequest.php b/src/Http/Requests/ApiSettingRequest.php index 32c60a4..3eccc8b 100644 --- a/src/Http/Requests/ApiSettingRequest.php +++ b/src/Http/Requests/ApiSettingRequest.php @@ -2,6 +2,7 @@ namespace Botble\Api\Http\Requests; +use Botble\Base\Rules\OnOffRule; use Botble\Support\Http\Requests\Request; class ApiSettingRequest extends Request @@ -9,7 +10,7 @@ class ApiSettingRequest extends Request public function rules(): array { return [ - 'api_enabled' => 'nullable|in:0,1', + 'api_enabled' => [new OnOffRule()], ]; } } diff --git a/src/Http/Requests/StoreSanctumTokenRequest.php b/src/Http/Requests/StoreSanctumTokenRequest.php new file mode 100644 index 0000000..40e55bb --- /dev/null +++ b/src/Http/Requests/StoreSanctumTokenRequest.php @@ -0,0 +1,16 @@ + ['required', 'string', 'max:255'], + 'abilities' => ['nullable', 'array'], + ]; + } +} diff --git a/src/Models/PersonalAccessToken.php b/src/Models/PersonalAccessToken.php new file mode 100644 index 0000000..453e9ca --- /dev/null +++ b/src/Models/PersonalAccessToken.php @@ -0,0 +1,16 @@ +app['config']->set([ + 'scribe.routes.0.match.prefixes' => ['api/*'], + 'scribe.routes.0.apply.headers' => [ + 'Authorization' => 'Bearer {token}', + 'Api-Version' => 'v1', + ], + ]); + if (class_exists('ApiHelper')) { AliasLoader::getInstance()->alias('ApiHelper', ApiHelper::class); } @@ -29,6 +36,10 @@ public function register(): void public function boot(): void { + if (version_compare('7.2.0', get_core_version(), '>')) { + return; + } + $this ->setNamespace('packages/api') ->loadRoutes() @@ -41,47 +52,40 @@ 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); } - - if (version_compare('7.0.0', get_core_version(), '>=')) { - DashboardMenu::registerItem([ - 'id' => 'cms-packages-api', - 'priority' => 9999, - 'parent_id' => 'cms-core-settings', - 'name' => 'packages/api::api.settings', - 'icon' => null, - 'url' => route('api.settings'), - 'permissions' => ['api.settings'], - ]); - } else { - PanelSectionManager::default() - ->registerItem( - SettingCommonPanelSection::class, - fn () => PanelSectionItem::make('settings.common.api') - ->setTitle(trans('packages/api::api.settings')) - ->withDescription(trans('packages/api::api.settings_description')) - ->withIcon('ti ti-api') - ->withPriority(110) - ->withRoute('api.settings') - ); - } }); - $this->app->booted(function () { - config([ - 'scribe.routes.0.match.prefixes' => ['api/*'], - 'scribe.routes.0.apply.headers' => [ - 'Authorization' => 'Bearer {token}', - 'Api-Version' => 'v1', - ], - ]); + PanelSectionManager::beforeRendering(function () { + PanelSectionManager::default() + ->registerItem( + SettingCommonPanelSection::class, + fn () => PanelSectionItem::make('settings.common.api') + ->setTitle(trans('packages/api::api.settings')) + ->withDescription(trans('packages/api::api.settings_description')) + ->withIcon('ti ti-api') + ->withPriority(110) + ->withRoute('api.settings') + ); }); } - protected function getPath(string $path = null): string + protected function getPath(string|null $path = null): string { return __DIR__ . '/../..' . ($path ? '/' . ltrim($path, '/') : ''); } diff --git a/src/Tables/SanctumTokenTable.php b/src/Tables/SanctumTokenTable.php new file mode 100644 index 0000000..a1d812b --- /dev/null +++ b/src/Tables/SanctumTokenTable.php @@ -0,0 +1,44 @@ +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(trans('packages/api::sanctum-token.abilities')), + DateTimeColumn::make('last_used_at') + ->label(trans('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', + ])); + } +}