Framework updates
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -396,6 +396,26 @@
|
||||
"created_at": "2026-01-29T08:19:02+00:00",
|
||||
"created_by": "root",
|
||||
"command": "php artisan make:migration:safe create_notifications_table"
|
||||
},
|
||||
"2026_01_29_180540_create_portal_users_table.php": {
|
||||
"created_at": "2026-01-29T18:05:40+00:00",
|
||||
"created_by": "root",
|
||||
"command": "php artisan make:migration:safe create_portal_users_table"
|
||||
},
|
||||
"2026_01_29_180545_create_portal_invitations_table.php": {
|
||||
"created_at": "2026-01-29T18:05:45+00:00",
|
||||
"created_by": "root",
|
||||
"command": "php artisan make:migration:safe create_portal_invitations_table"
|
||||
},
|
||||
"2026_01_29_180545_create_portal_sessions_table.php": {
|
||||
"created_at": "2026-01-29T18:05:45+00:00",
|
||||
"created_by": "root",
|
||||
"command": "php artisan make:migration:safe create_portal_sessions_table"
|
||||
},
|
||||
"2026_01_29_184331_create_portal_password_resets_table.php": {
|
||||
"created_at": "2026-01-29T18:43:31+00:00",
|
||||
"created_by": "root",
|
||||
"command": "php artisan make:migration:safe create_portal_password_resets_table"
|
||||
}
|
||||
}
|
||||
}
|
||||
57
database/migrations/2026_01_29_180540_create_portal_users_table.php
Executable file
57
database/migrations/2026_01_29_180540_create_portal_users_table.php
Executable file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* Portal users are external users (customers, clients, vendors) who access
|
||||
* a site through the client portal. They are completely separate from
|
||||
* internal system users (login_users).
|
||||
*
|
||||
* Key differences from login_users:
|
||||
* - Site-scoped (no multi-tenant access)
|
||||
* - Simpler auth model (no multi-site switching)
|
||||
* - Invite-only registration
|
||||
* - No remember_token (portal sessions are simpler)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
DB::statement("
|
||||
CREATE TABLE portal_users (
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
email VARCHAR(255) NOT NULL,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
is_verified TINYINT(1) NOT NULL DEFAULT 0,
|
||||
status_id BIGINT NOT NULL DEFAULT 1,
|
||||
metadata JSON NULL,
|
||||
last_login TIMESTAMP(3) NULL DEFAULT NULL,
|
||||
created_at TIMESTAMP(3) NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at TIMESTAMP(3) NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
created_by BIGINT DEFAULT NULL,
|
||||
updated_by BIGINT DEFAULT NULL,
|
||||
|
||||
UNIQUE KEY uk_portal_users_site_email (site_id, email),
|
||||
KEY idx_portal_users_site_id (site_id),
|
||||
KEY idx_portal_users_email (email),
|
||||
KEY idx_portal_users_status_id (status_id),
|
||||
KEY idx_portal_users_is_verified (is_verified),
|
||||
KEY idx_portal_users_created_at (created_at),
|
||||
KEY idx_portal_users_last_login (last_login),
|
||||
FOREIGN KEY (site_id) REFERENCES sites(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
");
|
||||
}
|
||||
|
||||
/**
|
||||
* down() method is prohibited in RSpade framework
|
||||
* Migrations should only move forward, never backward
|
||||
* You may remove this comment as soon as you see it and understand.
|
||||
*/
|
||||
};
|
||||
57
database/migrations/2026_01_29_180545_create_portal_invitations_table.php
Executable file
57
database/migrations/2026_01_29_180545_create_portal_invitations_table.php
Executable file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* Portal invitations are single-use codes that allow external users
|
||||
* to register for portal access. The invitation flow:
|
||||
*
|
||||
* 1. Admin creates invitation with email + optional metadata
|
||||
* 2. System sends email with unique invitation code
|
||||
* 3. User clicks link, lands on portal registration page
|
||||
* 4. User sets password, account created with email verified
|
||||
* 5. Invitation marked as used (used_at set)
|
||||
*
|
||||
* Metadata allows linking portal user to business entities
|
||||
* (e.g., contact_id, client_id) - application-specific.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
DB::statement("
|
||||
CREATE TABLE portal_invitations (
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
email VARCHAR(255) NOT NULL,
|
||||
invitation_code VARCHAR(64) NOT NULL,
|
||||
metadata JSON NULL,
|
||||
expires_at TIMESTAMP(3) NOT NULL,
|
||||
used_at TIMESTAMP(3) NULL DEFAULT NULL,
|
||||
created_at TIMESTAMP(3) NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at TIMESTAMP(3) NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
created_by BIGINT DEFAULT NULL,
|
||||
updated_by BIGINT DEFAULT NULL,
|
||||
|
||||
UNIQUE KEY uk_portal_invitations_code (invitation_code),
|
||||
KEY idx_portal_invitations_site_id (site_id),
|
||||
KEY idx_portal_invitations_email (email),
|
||||
KEY idx_portal_invitations_site_email (site_id, email),
|
||||
KEY idx_portal_invitations_expires_at (expires_at),
|
||||
KEY idx_portal_invitations_used_at (used_at),
|
||||
FOREIGN KEY (site_id) REFERENCES sites(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
");
|
||||
}
|
||||
|
||||
/**
|
||||
* down() method is prohibited in RSpade framework
|
||||
* Migrations should only move forward, never backward
|
||||
* You may remove this comment as soon as you see it and understand.
|
||||
*/
|
||||
};
|
||||
53
database/migrations/2026_01_29_180545_create_portal_sessions_table.php
Executable file
53
database/migrations/2026_01_29_180545_create_portal_sessions_table.php
Executable file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* Portal sessions are completely separate from internal sessions.
|
||||
* This ensures:
|
||||
* - Different cookie names (no session bleeding)
|
||||
* - Independent session management
|
||||
* - Simpler structure (no experience_id, no multi-site)
|
||||
*
|
||||
* Portal sessions are site-scoped - a portal user can only
|
||||
* be logged into one site at a time with a given session.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
DB::statement("
|
||||
CREATE TABLE portal_sessions (
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
portal_user_id BIGINT NULL,
|
||||
session_token VARCHAR(64) NOT NULL,
|
||||
csrf_token VARCHAR(64) NULL,
|
||||
ip_address VARCHAR(45) NOT NULL,
|
||||
user_agent VARCHAR(255) NULL,
|
||||
last_active TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
created_at TIMESTAMP(3) NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at TIMESTAMP(3) NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
|
||||
UNIQUE KEY uk_portal_sessions_token (session_token),
|
||||
KEY idx_portal_sessions_site_id (site_id),
|
||||
KEY idx_portal_sessions_portal_user_id (portal_user_id),
|
||||
KEY idx_portal_sessions_last_active (last_active),
|
||||
KEY idx_portal_sessions_site_user (site_id, portal_user_id),
|
||||
FOREIGN KEY (site_id) REFERENCES sites(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (portal_user_id) REFERENCES portal_users(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
");
|
||||
}
|
||||
|
||||
/**
|
||||
* down() method is prohibited in RSpade framework
|
||||
* Migrations should only move forward, never backward
|
||||
* You may remove this comment as soon as you see it and understand.
|
||||
*/
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* Portal password reset tokens allow users to reset their password.
|
||||
* Tokens are single-use and expire after a configurable time period.
|
||||
*
|
||||
* Flow:
|
||||
* 1. User requests password reset with their email
|
||||
* 2. System creates token and sends email with reset link
|
||||
* 3. User clicks link, lands on password reset page
|
||||
* 4. User sets new password
|
||||
* 5. Token marked as used (used_at set)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
DB::statement("
|
||||
CREATE TABLE portal_password_resets (
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
portal_user_id BIGINT NOT NULL,
|
||||
token VARCHAR(128) NOT NULL,
|
||||
expires_at TIMESTAMP(3) NOT NULL,
|
||||
used_at TIMESTAMP(3) NULL DEFAULT NULL,
|
||||
created_at TIMESTAMP(3) NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at TIMESTAMP(3) NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
|
||||
UNIQUE KEY uk_portal_password_resets_token (token),
|
||||
KEY idx_portal_password_resets_site_id (site_id),
|
||||
KEY idx_portal_password_resets_portal_user_id (portal_user_id),
|
||||
KEY idx_portal_password_resets_expires_at (expires_at),
|
||||
KEY idx_portal_password_resets_used_at (used_at),
|
||||
FOREIGN KEY (site_id) REFERENCES sites(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (portal_user_id) REFERENCES portal_users(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
");
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user