Implement Phase 1: Foundation & Core Setup
Complete foundation for the EZSCALE billing platform replacing WHMCS: - Install Composer deps (Fortify, Passport, Cashier, PayPal, Spatie Permissions, Inertia) - Install Vue 3 + Inertia.js with Vite, 3 layouts (App, Auth, Admin) - Configure subdomain routing (marketing, account, admin) with domain-based route files - Create 30 database migrations (15 custom tables + package defaults) - Create 14 Eloquent models with relationships, factories, and encrypted casts - Set up Fortify auth with 7 Vue pages (Login, Register, ForgotPassword, ResetPassword, VerifyEmail, ConfirmPassword, TwoFactorChallenge) - Add 2FA TOTP setup page with QR code and recovery codes - Configure middleware (Inertia, Spatie roles/permissions, EnsureUserNotSuspended) - Create seeders for roles/permissions, sample plans, and admin user - Build dashboard controllers and Vue pages for customer and admin panels - Add 4 shared Vue components (Card, Button, NavLink, FlashMessages) - Generate Passport OAuth2 keys for future SSO/API use - Write 24 Pest tests (auth, role-based access, models) — all passing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
51
website/database/seeders/AdminUserSeeder.php
Normal file
51
website/database/seeders/AdminUserSeeder.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class AdminUserSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$admin = User::firstOrCreate(
|
||||
['email' => 'admin@ezscale.cloud'],
|
||||
[
|
||||
'name' => 'Admin User',
|
||||
'password' => Hash::make('admin123!'),
|
||||
'status' => 'active',
|
||||
'email_verified_at' => now(),
|
||||
]
|
||||
);
|
||||
|
||||
if (! $admin->hasRole('admin')) {
|
||||
$admin->assignRole('admin');
|
||||
}
|
||||
|
||||
if (! $admin->profile) {
|
||||
$admin->profile()->create([]);
|
||||
}
|
||||
|
||||
$customer = User::firstOrCreate(
|
||||
['email' => 'user@ezscale.dev'],
|
||||
[
|
||||
'name' => 'Test Customer',
|
||||
'password' => Hash::make('user123!'),
|
||||
'status' => 'active',
|
||||
'email_verified_at' => now(),
|
||||
]
|
||||
);
|
||||
|
||||
if (! $customer->hasRole('customer')) {
|
||||
$customer->assignRole('customer');
|
||||
}
|
||||
|
||||
if (! $customer->profile) {
|
||||
$customer->profile()->create([]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
use WithoutModelEvents;
|
||||
|
||||
/**
|
||||
* Seed the application's database.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
// User::factory(10)->create();
|
||||
|
||||
User::factory()->create([
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
$this->call([
|
||||
RoleAndPermissionSeeder::class,
|
||||
PlanSeeder::class,
|
||||
AdminUserSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
89
website/database/seeders/PlanSeeder.php
Normal file
89
website/database/seeders/PlanSeeder.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Plan;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class PlanSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$plans = [
|
||||
// VPS Plans
|
||||
[
|
||||
'name' => 'VPS Starter',
|
||||
'slug' => 'vps-starter',
|
||||
'description' => 'Perfect for small projects and development.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 5.99,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => ['cpu' => '1 vCPU', 'ram' => '1GB', 'disk' => '25GB SSD', 'bandwidth' => '1TB'],
|
||||
'sort_order' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'VPS Pro',
|
||||
'slug' => 'vps-pro',
|
||||
'description' => 'Ideal for growing applications and websites.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 19.99,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => ['cpu' => '2 vCPU', 'ram' => '4GB', 'disk' => '80GB SSD', 'bandwidth' => '3TB'],
|
||||
'sort_order' => 2,
|
||||
],
|
||||
[
|
||||
'name' => 'VPS Enterprise',
|
||||
'slug' => 'vps-enterprise',
|
||||
'description' => 'High-performance VPS for demanding workloads.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 49.99,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => ['cpu' => '4 vCPU', 'ram' => '16GB', 'disk' => '200GB SSD', 'bandwidth' => '10TB'],
|
||||
'sort_order' => 3,
|
||||
],
|
||||
// Dedicated Server Plans
|
||||
[
|
||||
'name' => 'Dedicated Starter',
|
||||
'slug' => 'dedicated-starter',
|
||||
'description' => 'Entry-level dedicated server.',
|
||||
'service_type' => 'dedicated',
|
||||
'price' => 99.99,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => ['cpu' => 'Intel Xeon E-2236', 'ram' => '32GB DDR4', 'disk' => '2x 500GB SSD', 'bandwidth' => '10TB'],
|
||||
'stock_quantity' => 5,
|
||||
'sort_order' => 10,
|
||||
],
|
||||
// Web Hosting Plans
|
||||
[
|
||||
'name' => 'Hosting Basic',
|
||||
'slug' => 'hosting-basic',
|
||||
'description' => 'Shared hosting for small websites.',
|
||||
'service_type' => 'hosting',
|
||||
'price' => 3.99,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => ['disk' => '10GB SSD', 'bandwidth' => '100GB', 'domains' => '1', 'email' => '5 accounts'],
|
||||
'sort_order' => 20,
|
||||
],
|
||||
// Game Server Plans
|
||||
[
|
||||
'name' => 'Minecraft Standard',
|
||||
'slug' => 'minecraft-standard',
|
||||
'description' => 'Minecraft server for up to 20 players.',
|
||||
'service_type' => 'game_server',
|
||||
'price' => 9.99,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => ['cpu' => '2 vCPU', 'ram' => '4GB', 'disk' => '30GB SSD', 'players' => '20'],
|
||||
'sort_order' => 30,
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($plans as $plan) {
|
||||
Plan::create(array_merge([
|
||||
'currency' => 'USD',
|
||||
'status' => 'active',
|
||||
], $plan));
|
||||
}
|
||||
}
|
||||
}
|
||||
36
website/database/seeders/RoleAndPermissionSeeder.php
Normal file
36
website/database/seeders/RoleAndPermissionSeeder.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Spatie\Permission\Models\Permission;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
class RoleAndPermissionSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
|
||||
|
||||
$permissions = [
|
||||
'manage users',
|
||||
'manage services',
|
||||
'manage plans',
|
||||
'manage invoices',
|
||||
'manage coupons',
|
||||
'view audit logs',
|
||||
'impersonate users',
|
||||
];
|
||||
|
||||
foreach ($permissions as $permission) {
|
||||
Permission::create(['name' => $permission]);
|
||||
}
|
||||
|
||||
$adminRole = Role::create(['name' => 'admin']);
|
||||
$adminRole->givePermissionTo(Permission::all());
|
||||
|
||||
Role::create(['name' => 'customer']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user