Add api keys
This commit is contained in:
		
							parent
							
								
									970d2b0f0f
								
							
						
					
					
						commit
						4e0aaedc86
					
				
							
								
								
									
										190
									
								
								app/Filament/Resources/ApiKeyResource.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								app/Filament/Resources/ApiKeyResource.php
									
									
									
									
									
										Normal file
									
								
							| @ -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
									
								
								app/Filament/Resources/ApiKeyResource/Pages/CreateApiKey.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/Filament/Resources/ApiKeyResource/Pages/CreateApiKey.php
									
									
									
									
									
										Normal file
									
								
							| @ -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
									
								
								app/Filament/Resources/ApiKeyResource/Pages/ListApiKeys.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								app/Filament/Resources/ApiKeyResource/Pages/ListApiKeys.php
									
									
									
									
									
										Normal file
									
								
							| @ -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'; | ||||
|     } | ||||
| } | ||||
| @ -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. | ||||
|      */ | ||||
| @ -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, | ||||
|     ]; | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Lance Pioch
						Lance Pioch