feat: initial commit — UniFi snap-in package

Full UniFi dashboard snap-in including:
- WiFi/client/device stats with time-series snapshots
- Client Dashboard with traffic, satisfaction, signal, download charts
- Webhook alerting with debounced offline/online detection
- AP snapshot collection, client snapshot collection
- Device classification (type and OS) from OUI/hostname heuristics
- Webhook cooldown, templates, and multi-platform delivery

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Joel Wedemire
2026-04-12 23:00:05 -07:00
commit ce3217d8f4
29 changed files with 2972 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
// VLAN mapping rules: OU/group → VLAN + device limit + session duration
Schema::create('unifi_vlan_mappings', function (Blueprint $table) {
$table->id();
$table->string('group_name', 255); // Google OU or group name
$table->string('match_type', 20) // 'ou', 'group', 'email_domain', 'default'
->default('group');
$table->string('match_value', 255); // the value to match against
$table->unsignedSmallInteger('vlan_id'); // VLAN to assign
$table->unsignedTinyInteger('max_devices') // max concurrent devices
->default(1);
$table->unsignedInteger('session_minutes') // portal session duration
->default(720);
$table->unsignedSmallInteger('sort_order')
->default(0);
$table->timestamps();
});
// Known MAC addresses → direct VLAN assignment (no portal needed)
Schema::create('unifi_known_macs', function (Blueprint $table) {
$table->id();
$table->string('mac_address', 17)->unique(); // aa:bb:cc:dd:ee:ff
$table->string('device_name', 255)->nullable();
$table->string('device_type', 100)->nullable(); // chromebook, printer, phone, etc.
$table->string('owner', 255)->nullable(); // who it belongs to
$table->unsignedSmallInteger('vlan_id');
$table->text('notes')->nullable();
$table->timestamps();
});
// Active portal sessions (tracks who's connected via captive portal)
Schema::create('unifi_portal_sessions', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('mac_address', 17);
$table->string('device_hostname', 255)->nullable();
$table->string('device_os', 100)->nullable(); // detected OS
$table->string('device_type', 100)->nullable(); // detected device category
$table->string('ssid', 100)->nullable();
$table->unsignedSmallInteger('vlan_id')->nullable();
$table->string('ap_mac', 17)->nullable();
$table->boolean('is_active')->default(true);
$table->timestamp('authorized_at');
$table->timestamp('expires_at')->nullable();
$table->timestamps();
$table->index(['user_id', 'is_active']);
$table->index('mac_address');
});
}
public function down(): void
{
Schema::dropIfExists('unifi_portal_sessions');
Schema::dropIfExists('unifi_known_macs');
Schema::dropIfExists('unifi_vlan_mappings');
}
};