Skip to content

Commit

Permalink
Add api keys
Browse files Browse the repository at this point in the history
  • Loading branch information
lancepioch committed Apr 8, 2024
1 parent 970d2b0 commit 4e0aaed
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 0 deletions.
190 changes: 190 additions & 0 deletions app/Filament/Resources/ApiKeyResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
<?php

namespace App\Filament\Resources;

use App\Filament\Resources\ApiKeyResource\Pages;
use App\Models\ApiKey;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Components\Tab;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;

class ApiKeyResource extends Resource
{
protected static ?string $model = ApiKey::class;
protected static ?string $label = 'API Key';

protected static ?string $navigationIcon = 'tabler-key';

public static function canEdit($record): bool
{
return false;
}

public function getTabs(): array
{
return [
'all' => Tab::make('All Keys'),
'application' => Tab::make('Application Keys')
->modifyQueryUsing(fn (Builder $query) => $query->where('key_type', ApiKey::TYPE_APPLICATION)),
];
}

public function getDefaultActiveTab(): string | int | null
{
return 'application';
}

public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Hidden::make('identifier')->default(ApiKey::generateTokenIdentifier(ApiKey::TYPE_APPLICATION)),
Forms\Components\Hidden::make('token')->default(encrypt(str_random(ApiKey::KEY_LENGTH))),

Forms\Components\Select::make('user_id')
->searchable()
->preload()
->relationship('user', 'username')
->default(auth()->user()->id)
->required(),

Forms\Components\Select::make('key_type')
->options(function (ApiKey $apiKey) {
$originalOptions = [
ApiKey::TYPE_NONE => 'None',
ApiKey::TYPE_ACCOUNT => 'Account',
ApiKey::TYPE_APPLICATION => 'Application',
ApiKey::TYPE_DAEMON_USER => 'Daemon User',
ApiKey::TYPE_DAEMON_APPLICATION => 'Daemon Application',
];

return collect($originalOptions)
->filter(fn ($value, $key) => $key <= ApiKey::TYPE_APPLICATION || $apiKey->key_type === $key)
->all();
})
->selectablePlaceholder(false)
->required()
->default(ApiKey::TYPE_APPLICATION),

Forms\Components\Fieldset::make('Permissions')->schema(
collect(ApiKey::RESOURCES)->map(fn ($resource) =>
Forms\Components\ToggleButtons::make("r_$resource")
->label(str($resource)->replace('_', ' ')->title())
->options([
0 => 'None',
1 => 'Read',
// 2 => 'Write',
3 => 'Read & Write',
])
->icons([
0 => 'tabler-book-off',
1 => 'tabler-book',
2 => 'tabler-writing',
3 => 'tabler-writing',
])
->colors([
0 => 'primary',
1 => 'warning',
2 => 'danger',
3 => 'danger',
])
->inline()
->required()
->disabledOn('edit')
->default(0),
)->all(),
),

Forms\Components\TagsInput::make('allowed_ips')
->placeholder('Example: 127.0.0.1 or 192.168.1.1')
->label('Whitelisted IPv4 Addresses')
->helperText('Press enter to add a new IP address or leave blank to allow any IP address')
->columnSpanFull()
->hidden()
->default(null),

Forms\Components\Textarea::make('memo')
->required()
->label('Description')
->helperText('
Once you have assigned permissions and created this set of credentials you will be unable to come back and edit it.
If you need to make changes down the road you will need to create a new set of credentials.
')
->columnSpanFull(),
]);
}

public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('user.username')
->searchable()
->hidden()
->sortable(),

Tables\Columns\TextColumn::make('key_type')
->label('Type')
->state(fn (ApiKey $key) => $key->type())
->hidden()
->sortable(),

Tables\Columns\TextColumn::make('key')
->copyable()
->state(fn (ApiKey $key) => $key->identifier . decrypt($key->token)),

Tables\Columns\TextColumn::make('memo')
->wrap()
->limit(50),

Tables\Columns\TextColumn::make('identifier')
->hidden()
->searchable(),

Tables\Columns\TextColumn::make('last_used_at')
->dateTime()
->sortable()
->toggleable(),

Tables\Columns\TextColumn::make('expires_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),

Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}

public static function getRelations(): array
{
return [
//
];
}

public static function getPages(): array
{
return [
'index' => Pages\ListApiKeys::route('/'),
'create' => Pages\CreateApiKey::route('/create'),
];
}
}
12 changes: 12 additions & 0 deletions app/Filament/Resources/ApiKeyResource/Pages/CreateApiKey.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace App\Filament\Resources\ApiKeyResource\Pages;

use App\Filament\Resources\ApiKeyResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;

class CreateApiKey extends CreateRecord
{
protected static string $resource = ApiKeyResource::class;
}
42 changes: 42 additions & 0 deletions app/Filament/Resources/ApiKeyResource/Pages/ListApiKeys.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace App\Filament\Resources\ApiKeyResource\Pages;

use App\Filament\Resources\ApiKeyResource;
use App\Models\ApiKey;
use Filament\Actions;
use Filament\Resources\Components\Tab;
use Filament\Resources\Pages\ListRecords;
use Illuminate\Database\Eloquent\Builder;

class ListApiKeys extends ListRecords
{
protected static string $resource = ApiKeyResource::class;

protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}

public function getTabs(): array
{
return [
'all' => Tab::make('All Keys'),
'application' => Tab::make('Application Keys')
->modifyQueryUsing(fn (Builder $query) =>
$query->where('key_type', ApiKey::TYPE_APPLICATION)
),
'account' => Tab::make('Account Keys')
->modifyQueryUsing(fn (Builder $query) =>
$query->where('key_type', ApiKey::TYPE_ACCOUNT)
),
];
}

public function getDefaultActiveTab(): string | int | null
{
return 'application';
}
}
11 changes: 11 additions & 0 deletions app/Models/ApiKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class ApiKey extends Model
*/
public const KEY_LENGTH = 32;

public const RESOURCES = ['servers', 'nodes', 'allocations', 'users', 'eggs', 'database_hosts', 'server_databases'];

/**
* The table associated with the model.
*/
Expand All @@ -92,12 +94,21 @@ class ApiKey extends Model
* Fields that are mass assignable.
*/
protected $fillable = [
'user_id',
'key_type',
'identifier',
'token',
'allowed_ips',
'memo',
'last_used_at',
'expires_at',
'r_' . AdminAcl::RESOURCE_USERS,
'r_' . AdminAcl::RESOURCE_ALLOCATIONS,
'r_' . AdminAcl::RESOURCE_DATABASE_HOSTS,
'r_' . AdminAcl::RESOURCE_SERVER_DATABASES,
'r_' . AdminAcl::RESOURCE_EGGS,
'r_' . AdminAcl::RESOURCE_NODES,
'r_' . AdminAcl::RESOURCE_SERVERS,
];

/**
Expand Down

0 comments on commit 4e0aaed

Please sign in to comment.