Xgenious/ docs
Products
Get support

Plugin Permissions

Define custom permissions for your plugin in plugin.json.

Permission Structure

{
  "permissions": [
    {
      "id": "manage_plugin",
      "label": "Manage Plugin",
      "description": "Full access to plugin settings and configuration"
    },
    {
      "id": "view_plugin_logs",
      "label": "View Plugin Logs",
      "description": "View plugin activity and error logs"
    },
    {
      "id": "export_plugin_data",
      "label": "Export Plugin Data",
      "description": "Export plugin data to CSV or JSON"
    }
  ]
}

Permission Properties

PropertyTypeDescription
idstringUnique permission identifier
labelstringHuman-readable permission name
descriptionstringDetailed explanation of what permission allows

Checking Permissions

In routes and controllers, verify user permissions:

<?php

namespace MyVendor\MyPlugin\Http\Controllers;

use Illuminate\Http\Request;

class SettingsController
{
    public function index(Request $request)
    {
        // Authorize user
        $request->user()->authorize('my-plugin:manage_plugin');

        // Get settings
        $settings = get_plugin_settings('my-plugin');

        return view('my-plugin::settings', ['settings' => $settings]);
    }

    public function store(Request $request)
    {
        // Authorize user
        $request->user()->authorize('my-plugin:manage_plugin');

        // Validate and save
        $validated = $request->validate([
            'api_key' => 'required|string',
            'webhook_url' => 'required|url',
        ]);

        save_plugin_settings('my-plugin', $validated);

        return redirect()->back()->with('success', 'Settings saved');
    }
}

Authorization Middleware

Create a custom middleware for permission checking:

<?php

namespace MyVendor\MyPlugin\Http\Middleware;

use Closure;

class CheckPluginPermission
{
    public function handle($request, Closure $next, $permission)
    {
        if (!$request->user()->can('my-plugin:' . $permission)) {
            abort(403, 'Unauthorized');
        }

        return $next($request);
    }
}

Use in routes:

Route::middleware(['auth', 'check-plugin-permission:manage_plugin'])->group(function () {
    Route::get('/admin/my-plugin/settings', 'SettingsController@index');
});

Role-Based Permissions

Assign permissions to roles:

// In plugin bootstrap or migration
$admin = Role::where('slug', 'administrator')->first();
$admin->attachPermissions([
    'my-plugin:manage_plugin',
    'my-plugin:view_plugin_logs',
    'my-plugin:export_plugin_data',
]);

$editor = Role::where('slug', 'editor')->first();
$editor->attachPermission('my-plugin:view_plugin_logs');

Plugin Settings

Store plugin configuration in the database.

Default Settings

Define defaults in plugin.json:

{
  "settings": {
    "api_key": "",
    "webhook_url": "",
    "enable_notifications": true,
    "max_retries": 3,
    "timeout_seconds": 30
  }
}

Getting Settings

// Get all settings
$settings = get_plugin_settings('my-plugin');

// Get specific setting
$apiKey = get_plugin_setting('my-plugin', 'api_key');

// Get with default value
$timeout = get_plugin_setting('my-plugin', 'timeout_seconds', 30);

Saving Settings

// Save all settings
save_plugin_settings('my-plugin', [
    'api_key' => 'new-key',
    'webhook_url' => 'https://example.com/webhook',
    'enable_notifications' => false,
]);

// Update single setting
update_plugin_setting('my-plugin', 'api_key', 'updated-key');

Settings UI

Create a settings form in your view:

<form action="{{ route('my-plugin.settings.store') }}" method="POST">
    @csrf

    <div class="form-group">
        <label for="api_key">API Key</label>
        <input type="text" id="api_key" name="api_key" value="{{ $settings['api_key'] ?? '' }}" />
    </div>

    <div class="form-group">
        <label for="webhook_url">Webhook URL</label>
        <input type="url" id="webhook_url" name="webhook_url" value="{{ $settings['webhook_url'] ?? '' }}" />
    </div>

    <div class="form-group">
        <label>
            <input type="checkbox" name="enable_notifications" {{ ($settings['enable_notifications'] ?? false) ? 'checked' : '' }} />
            Enable Notifications
        </label>
    </div>

    <button type="submit">Save Settings</button>
</form>

Plugin Data Storage

Store plugin-specific data using Laravel models or the plugin data table.

Using Plugin Data Table

Store key-value data:

// Save data
save_plugin_data('my-plugin', 'key', 'value');

// Get data
$value = get_plugin_data('my-plugin', 'key');

// Delete data
delete_plugin_data('my-plugin', 'key');

// Get all data
$allData = get_plugin_data('my-plugin');

Using Eloquent Models

Create plugin models for structured data:

<?php

namespace MyVendor\MyPlugin\Models;

use Illuminate\Database\Eloquent\Model;

class PluginCampaign extends Model
{
    protected $table = 'plugin_campaigns';
    protected $fillable = ['plugin_id', 'name', 'config'];
    protected $casts = ['config' => 'json'];
}

Database Migrations

Create tables in migrations:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePluginCampaignsTable extends Migration
{
    public function up()
    {
        Schema::create('plugin_campaigns', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->json('config')->nullable();
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('plugin_campaigns');
    }
}

Data Relationships

Link plugin data to core entities:

<?php

namespace MyVendor\MyPlugin\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class PluginCampaign extends Model
{
    protected $table = 'plugin_campaigns';

    public function campaign(): BelongsTo
    {
        return $this->belongsTo(\App\Models\Campaign::class, 'campaign_id');
    }

    public function user(): BelongsTo
    {
        return $this->belongsTo(\App\Models\User::class, 'user_id');
    }
}

Data Export & Cleanup

Implement data management for plugin lifecycle.

Exporting Data

Create export functionality:

<?php

namespace MyVendor\MyPlugin\Services;

use Illuminate\Support\Facades\Storage;

class ExportService
{
    public function exportToCSV()
    {
        $campaigns = PluginCampaign::all();
        $csv = "Name,Config\n";

        foreach ($campaigns as $campaign) {
            $csv .= "{$campaign->name}," . json_encode($campaign->config) . "\n";
        }

        $filename = 'plugin-export-' . now()->format('Y-m-d-His') . '.csv';
        Storage::disk('local')->put("exports/{$filename}", $csv);

        return "exports/{$filename}";
    }
}

Cleanup on Uninstall

In your uninstall() method, clean up all data:

public function uninstall(): void
{
    // Delete tables (via migrations rollback)
    Artisan::call('migrate:rollback', [
        '--path' => __DIR__ . '/../../database/migrations',
    ]);

    // Clean plugin data
    DB::table('plugin_data')->where('plugin', $this->getName())->delete();

    // Delete exported files
    Storage::disk('local')->deleteDirectory('plugins/' . $this->getName());
}

Best Practices

Security

  • Validate inputs: Always validate settings and data from users
  • Use CSRF tokens: Include @csrf in all forms
  • Escape output: Use Laravel's escaping helpers
  • Hash sensitive data: Use bcrypt for passwords, hash for API keys

Performance

  • Cache settings: Cache plugin settings to avoid repeated database queries
  • Index tables: Add indexes to frequently queried plugin data
  • Paginate results: Use pagination for large data sets

Testing

Write tests for permissions and data access:

public function test_unauthorized_user_cannot_access_settings()
{
    $user = User::factory()->create();
    
    $response = $this->actingAs($user)->get('/admin/my-plugin/settings');
    
    $response->assertStatus(403);
}

Next Steps

Still stuck?
Our support team is ready to help you get set up.
Get support