Replace Auth System #3
@@ -103,7 +103,7 @@ class User extends Authenticatable
|
|||||||
{
|
{
|
||||||
if ($this->discord_id && $this->discord_avatar && !$this->avatar)
|
if ($this->discord_id && $this->discord_avatar && !$this->avatar)
|
||||||
{
|
{
|
||||||
return "https://external-content.duckduckgo.com/iu/?u=https://cdn.discordapp.com/avatars/{$this->discord_id}/{$this->discord_avatar}.webp";
|
return $this->discord_avatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->avatar)
|
if ($this->avatar)
|
||||||
|
|||||||
@@ -1,154 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*/
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
// 1. Create new column discord_id
|
|
||||||
Schema::table('users', function (Blueprint $table) {
|
|
||||||
$table->unsignedBigInteger('discord_id')->nullable()->after('id');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2. Migrate Discord Users IDs
|
|
||||||
DB::table('users')
|
|
||||||
->where('id', '>', 10000)
|
|
||||||
->update(['discord_id' => DB::raw('id')]);
|
|
||||||
|
|
||||||
// 3. Temporary new auto increment column
|
|
||||||
Schema::table('users', function (Blueprint $table) {
|
|
||||||
$table->unsignedBigInteger('new_id')->first();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 3.5 Manually count (cursed)
|
|
||||||
$counter = 1;
|
|
||||||
foreach(User::orderBy('id')->get() as $user) {
|
|
||||||
$user->new_id = $counter;
|
|
||||||
$user->save();
|
|
||||||
$counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Drop foreign keys
|
|
||||||
$this->dropForeignKeys();
|
|
||||||
|
|
||||||
// 5. Fix ID's in other tables
|
|
||||||
$this->updateUserIDsInOtherTables();
|
|
||||||
|
|
||||||
// 6. Remove old ID
|
|
||||||
Schema::table('users', function (Blueprint $table) {
|
|
||||||
$table->bigInteger('id')->unsigned()->change();
|
|
||||||
$table->dropPrimary('id');
|
|
||||||
$table->dropColumn('id');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 7. Rename new_id to id
|
|
||||||
Schema::table('users', function (Blueprint $table) {
|
|
||||||
$table->renameColumn('new_id', 'id');
|
|
||||||
$table->unsignedBigInteger('id')->autoIncrement()->primary()->change();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 8. Recreate foreign key constraints
|
|
||||||
$this->addForeignKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Drop Foreign Keys referencing the user id
|
|
||||||
*/
|
|
||||||
private function dropForeignKeys(): void
|
|
||||||
{
|
|
||||||
Schema::table('markable_likes', function (Blueprint $table) {
|
|
||||||
$table->dropForeign(['user_id']);
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::table('watched', function (Blueprint $table) {
|
|
||||||
$table->dropForeign(['user_id']);
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::table('discord_access_tokens', function (Blueprint $table) {
|
|
||||||
$table->dropForeign(['user_id']);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Our Schema does include a foreign key, for whatever reason it doesn't exist in the first palce
|
|
||||||
// Schema::table('user_downloads', function (Blueprint $table) {
|
|
||||||
// $table->dropForeign(['user_id']);
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tables to fix the IDs:
|
|
||||||
* - comments ['commenter_id']
|
|
||||||
* - discord_access_tokens ['user_id']
|
|
||||||
* - markable_likes ['user_id']
|
|
||||||
* - notifications ['notifiable_id']
|
|
||||||
* - playlists ['user_id']
|
|
||||||
* - user_downloads ['user_id']
|
|
||||||
* - watched ['user_id']
|
|
||||||
*/
|
|
||||||
private function updateUserIDsInOtherTables(): void
|
|
||||||
{
|
|
||||||
|
|
||||||
DB::table('users')->orderBy('id')->chunk(100, function (Collection $users) {
|
|
||||||
foreach ($users as $user) {
|
|
||||||
DB::table('comments')
|
|
||||||
->where('commenter_id', $user->id)
|
|
||||||
->update(['commenter_id' => $user->new_id]);
|
|
||||||
|
|
||||||
DB::table('discord_access_tokens')
|
|
||||||
->where('user_id', $user->id)
|
|
||||||
->update(['user_id' => $user->new_id]);
|
|
||||||
|
|
||||||
DB::table('markable_likes')
|
|
||||||
->where('user_id', $user->id)
|
|
||||||
->update(['user_id' => $user->new_id]);
|
|
||||||
|
|
||||||
DB::table('notifications')
|
|
||||||
->where('notifiable_id', $user->id)
|
|
||||||
->update(['notifiable_id' => $user->new_id]);
|
|
||||||
|
|
||||||
DB::table('playlists')
|
|
||||||
->where('user_id', $user->id)
|
|
||||||
->update(['user_id' => $user->new_id]);
|
|
||||||
|
|
||||||
DB::table('user_downloads')
|
|
||||||
->where('user_id', $user->id)
|
|
||||||
->update(['user_id' => $user->new_id]);
|
|
||||||
|
|
||||||
DB::table('watched')
|
|
||||||
->where('user_id', $user->id)
|
|
||||||
->update(['user_id' => $user->new_id]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-Add Foreign Keys to tables which we dropped previously
|
|
||||||
*/
|
|
||||||
private function addForeignKeys(): void
|
|
||||||
{
|
|
||||||
Schema::table('markable_likes', function (Blueprint $table) {
|
|
||||||
$table->unsignedBigInteger('user_id')->references('id')->on('users')->onDelete('cascade')->change();
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::table('watched', function (Blueprint $table) {
|
|
||||||
$table->unsignedBigInteger('user_id')->references('id')->on('users')->onDelete('cascade')->change();
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::table('discord_access_tokens', function (Blueprint $table) {
|
|
||||||
$table->unsignedBigInteger('user_id')->references('id')->on('users')->onDelete('cascade')->change();
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::table('user_downloads', function (Blueprint $table) {
|
|
||||||
$table->unsignedBigInteger('user_id')->references('id')->on('users')->onDelete('cascade')->change();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
@@ -44,5 +45,21 @@ return new class extends Migration
|
|||||||
$table->string('password')->nullable()->after('email_verified_at');
|
$table->string('password')->nullable()->after('email_verified_at');
|
||||||
$table->rememberToken()->after('password');
|
$table->rememberToken()->after('password');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
* Fix Discord Profile Pictures
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
* The oauth package by socialite now returns a full url of the avatar.
|
||||||
|
* Meaning all the old entries have to be fixed.
|
||||||
|
*/
|
||||||
|
foreach (User::whereNotNull('discord_avatar')->get() as $user)
|
||||||
|
{
|
||||||
|
$isGif = preg_match('/a_.+/m', $user->discord_avatar) === 1;
|
||||||
|
$extension = $isGif ? 'gif' : 'webp';
|
||||||
|
$user->discord_avatar = sprintf('https://cdn.discordapp.com/avatars/%s/%s.%s', $user->id, $user->discord_avatar, $extension);
|
||||||
|
$user->save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
207
database/migrations/2026_01_08_213625_fix_database_structure.php
Normal file
207
database/migrations/2026_01_08_213625_fix_database_structure.php
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Playlist;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
// 1. Create new column discord_id
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->unsignedBigInteger('discord_id')->nullable()->after('id');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Migrate Discord Users IDs
|
||||||
|
DB::table('users')
|
||||||
|
->where('id', '>', 10000)
|
||||||
|
->update(['discord_id' => DB::raw('id')]);
|
||||||
|
|
||||||
|
// 3. Temporary new auto increment column
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->unsignedBigInteger('new_id')->first();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3.5 Count
|
||||||
|
DB::statement('
|
||||||
|
UPDATE users u
|
||||||
|
JOIN (
|
||||||
|
SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS rn
|
||||||
|
FROM users
|
||||||
|
) t ON u.id = t.id
|
||||||
|
SET u.new_id = t.rn
|
||||||
|
');
|
||||||
|
|
||||||
|
// 4. Drop foreign keys
|
||||||
|
$this->dropForeignKeys();
|
||||||
|
|
||||||
|
// 5. Fix ID's in other tables
|
||||||
|
$this->updateUserIDsInOtherTables();
|
||||||
|
|
||||||
|
// 6. Remove old ID
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->bigInteger('id')->unsigned()->change();
|
||||||
|
$table->dropPrimary('id');
|
||||||
|
$table->dropColumn('id');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 7. Rename new_id to id
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('new_id', 'id');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 8. Change new ID to auto increment and set as primary key
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->unsignedBigInteger('id')->autoIncrement()->primary()->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 9. Remove data that would conflict with constraints
|
||||||
|
$this->deleteUnreferencedData();
|
||||||
|
|
||||||
|
// 9. Recreate foreign key constraints
|
||||||
|
$this->addForeignKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop Foreign Keys referencing the user id
|
||||||
|
*/
|
||||||
|
private function dropForeignKeys(): void
|
||||||
|
{
|
||||||
|
Schema::table('markable_likes', function (Blueprint $table) {
|
||||||
|
$table->dropForeign(['user_id']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('watched', function (Blueprint $table) {
|
||||||
|
$table->dropForeign(['user_id']);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Our Schema does include a foreign key, for whatever reason it doesn't exist in the first palce
|
||||||
|
// Schema::table('user_downloads', function (Blueprint $table) {
|
||||||
|
// $table->dropForeign(['user_id']);
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tables to fix the IDs:
|
||||||
|
* - comments ['commenter_id']
|
||||||
|
* - markable_likes ['user_id']
|
||||||
|
* - notifications ['notifiable_id']
|
||||||
|
* - playlists ['user_id']
|
||||||
|
* - user_downloads ['user_id']
|
||||||
|
* - watched ['user_id']
|
||||||
|
*/
|
||||||
|
private function updateUserIDsInOtherTables(): void
|
||||||
|
{
|
||||||
|
DB::statement('
|
||||||
|
UPDATE comments c
|
||||||
|
JOIN users u ON c.commenter_id = u.id
|
||||||
|
SET c.commenter_id = u.new_id
|
||||||
|
');
|
||||||
|
|
||||||
|
DB::statement('
|
||||||
|
UPDATE watched w
|
||||||
|
JOIN users u ON w.user_id = u.id
|
||||||
|
SET w.user_id = u.new_id
|
||||||
|
');
|
||||||
|
|
||||||
|
DB::statement('
|
||||||
|
UPDATE markable_likes ml
|
||||||
|
JOIN users u ON ml.user_id = u.id
|
||||||
|
SET ml.user_id = u.new_id
|
||||||
|
');
|
||||||
|
|
||||||
|
DB::statement('
|
||||||
|
UPDATE notifications n
|
||||||
|
JOIN users u ON n.notifiable_id = u.id
|
||||||
|
SET n.notifiable_id = u.new_id
|
||||||
|
');
|
||||||
|
|
||||||
|
DB::statement('
|
||||||
|
UPDATE playlists p
|
||||||
|
JOIN users u ON p.user_id = u.id
|
||||||
|
SET p.user_id = u.new_id
|
||||||
|
');
|
||||||
|
|
||||||
|
DB::statement('
|
||||||
|
UPDATE user_downloads ud
|
||||||
|
JOIN users u ON ud.user_id = u.id
|
||||||
|
SET ud.user_id = u.new_id
|
||||||
|
');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Due to incorrect handling of user deletes,
|
||||||
|
* we have unreferenced data
|
||||||
|
*/
|
||||||
|
private function deleteUnreferencedData(): void
|
||||||
|
{
|
||||||
|
// User Downloads Table
|
||||||
|
DB::table('user_downloads')
|
||||||
|
->where('user_id', '>', 1_000_000)
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
// User Playlists Table
|
||||||
|
$playlists = Playlist::where('user_id', '>', 1_000_000)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach($playlists as $playlist) {
|
||||||
|
DB::table('playlist_episodes')
|
||||||
|
->where('playlist_id', '=', $playlist->id)
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
$playlist->forceDelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-Add Foreign Keys to tables which we dropped previously
|
||||||
|
*/
|
||||||
|
private function addForeignKeys(): void
|
||||||
|
{
|
||||||
|
Schema::table('markable_likes', function (Blueprint $table) {
|
||||||
|
// Ensure the column is unsigned
|
||||||
|
$table->bigInteger('user_id')->unsigned()->change();
|
||||||
|
|
||||||
|
// Add the foreign key constraint
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('watched', function (Blueprint $table) {
|
||||||
|
// Ensure the column is unsigned
|
||||||
|
$table->bigInteger('user_id')->unsigned()->change();
|
||||||
|
|
||||||
|
// Add the foreign key constraint
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('user_downloads', function (Blueprint $table) {
|
||||||
|
// Ensure the column is unsigned
|
||||||
|
$table->bigInteger('user_id')->unsigned()->change();
|
||||||
|
|
||||||
|
// Add the foreign key constraint
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('playlist_episodes', function (Blueprint $table) {
|
||||||
|
// Ensure the column is unsigned
|
||||||
|
$table->bigInteger('playlist_id')->unsigned()->change();
|
||||||
|
|
||||||
|
// Add the foreign key constraint
|
||||||
|
$table->foreign('playlist_id')->references('id')->on('playlists')->onDelete('cascade');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('playlists', function (Blueprint $table) {
|
||||||
|
// Ensure the column is unsigned
|
||||||
|
$table->bigInteger('user_id')->unsigned()->change();
|
||||||
|
|
||||||
|
// Add the foreign key constraint
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user