Compare commits

..

No commits in common. "feat/validate-invitation-token-format" and "dev" have entirely different histories.

6 changed files with 6 additions and 153 deletions

View file

@ -102,7 +102,7 @@ class EntitlementApiController extends Controller
$workspace = Workspace::create([ $workspace = Workspace::create([
'name' => $user->name."'s Workspace", 'name' => $user->name."'s Workspace",
'slug' => Str::slug($user->name).'-'.Str::random(6), 'slug' => Str::slug($user->name).'-'.Str::random(6),
'domain' => 'hub.'.config('app.base_domain', 'host.uk.com'), 'domain' => 'hub.host.uk.com',
'type' => 'custom', 'type' => 'custom',
]); ]);

View file

@ -139,7 +139,7 @@ class WorkspaceController extends Controller
} }
// Set default domain // Set default domain
$validated['domain'] = 'hub.'.config('app.base_domain', 'host.uk.com'); $validated['domain'] = 'hub.host.uk.com';
$validated['type'] = $validated['type'] ?? 'custom'; $validated['type'] = $validated['type'] ?? 'custom';
$workspace = Workspace::create($validated); $workspace = Workspace::create($validated);
@ -261,7 +261,7 @@ class WorkspaceController extends Controller
->whereIn('workspace_id', function ($query) { ->whereIn('workspace_id', function ($query) {
$query->select('id') $query->select('id')
->from('workspaces') ->from('workspaces')
->where('domain', 'hub.'.config('app.base_domain', 'host.uk.com')); ->where('domain', 'hub.host.uk.com');
}) })
->update(['is_default' => false]); ->update(['is_default' => false]);

View file

@ -1,57 +0,0 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Add foreign key constraints on feature_code columns to prevent orphaned records.
*
* Fixes #12: feature_code in usage_alert_history not constrained to entitlement_features.
*/
public function up(): void
{
Schema::table('entitlement_usage_alert_history', function (Blueprint $table) {
$table->foreign('feature_code', 'usage_alert_feature_code_fk')
->references('code')
->on('entitlement_features')
->cascadeOnUpdate()
->restrictOnDelete();
});
Schema::table('entitlement_boosts', function (Blueprint $table) {
$table->foreign('feature_code', 'boosts_feature_code_fk')
->references('code')
->on('entitlement_features')
->cascadeOnUpdate()
->restrictOnDelete();
});
Schema::table('entitlement_usage_records', function (Blueprint $table) {
$table->foreign('feature_code', 'usage_records_feature_code_fk')
->references('code')
->on('entitlement_features')
->cascadeOnUpdate()
->restrictOnDelete();
});
}
public function down(): void
{
Schema::table('entitlement_usage_alert_history', function (Blueprint $table) {
$table->dropForeign('usage_alert_feature_code_fk');
});
Schema::table('entitlement_boosts', function (Blueprint $table) {
$table->dropForeign('boosts_feature_code_fk');
});
Schema::table('entitlement_usage_records', function (Blueprint $table) {
$table->dropForeign('usage_records_feature_code_fk');
});
}
};

View file

@ -1,40 +0,0 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Change namespaces.workspace_id FK from nullOnDelete to cascadeOnDelete.
*
* Fixes #10 — namespaces were orphaned with null workspace_id when
* the parent workspace was deleted.
*/
public function up(): void
{
Schema::table('namespaces', function (Blueprint $table) {
$table->dropForeign(['workspace_id']);
$table->foreign('workspace_id')
->references('id')
->on('workspaces')
->cascadeOnDelete();
});
}
public function down(): void
{
Schema::table('namespaces', function (Blueprint $table) {
$table->dropForeign(['workspace_id']);
$table->foreign('workspace_id')
->references('id')
->on('workspaces')
->nullOnDelete();
});
}
};

View file

@ -1,47 +0,0 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Change parent_feature_id FK from nullOnDelete to cascadeOnDelete.
*
* nullOnDelete orphans child features when a parent is removed they lose
* their hierarchy but still exist with a null parent_feature_id. Children
* that belong to a pool have no meaning without their parent, so cascade
* deletion is the correct behaviour.
*
* Fixes #40
*/
public function up(): void
{
Schema::table('entitlement_features', function (Blueprint $table) {
$table->dropForeign(['parent_feature_id']);
$table->foreign('parent_feature_id')
->references('id')
->on('entitlement_features')
->cascadeOnDelete();
});
}
/**
* Revert to the original nullOnDelete behaviour.
*/
public function down(): void
{
Schema::table('entitlement_features', function (Blueprint $table) {
$table->dropForeign(['parent_feature_id']);
$table->foreign('parent_feature_id')
->references('id')
->on('entitlement_features')
->nullOnDelete();
});
}
};

View file

@ -26,12 +26,10 @@ use Illuminate\Support\Facades\Route;
Route::prefix('account')->name('account.')->group(function () { Route::prefix('account')->name('account.')->group(function () {
Route::get('/delete/{token}', ConfirmDeletion::class) Route::get('/delete/{token}', ConfirmDeletion::class)
->name('delete.confirm') ->name('delete.confirm');
->where('token', '[a-zA-Z0-9]{64}');
Route::get('/delete/{token}/cancel', CancelDeletion::class) Route::get('/delete/{token}/cancel', CancelDeletion::class)
->name('delete.cancel') ->name('delete.cancel');
->where('token', '[a-zA-Z0-9]{64}');
}); });
/* /*
@ -45,8 +43,7 @@ Route::prefix('account')->name('account.')->group(function () {
*/ */
Route::get('/workspace/invitation/{token}', WorkspaceInvitationController::class) Route::get('/workspace/invitation/{token}', WorkspaceInvitationController::class)
->name('workspace.invitation.accept') ->name('workspace.invitation.accept');
->where('token', '[a-zA-Z0-9]{64}');
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------