Skip to content

Commit 492050e

Browse files
committed
hotfix: Convert cms_user's primary key as "bigint" instead of "uuid" to avoid "notification" table error
1. Remove custom notification table migration 2. Convert column type of pk of cms_users 3. Change current data 4. Change relation tables column type
1 parent cc66c45 commit 492050e

File tree

7 files changed

+380
-41
lines changed

7 files changed

+380
-41
lines changed
Lines changed: 332 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,332 @@
1+
<?php
2+
3+
use Illuminate\Database\Schema\Blueprint;
4+
use Illuminate\Support\Facades\DB;
5+
use Illuminate\Support\Facades\Schema;
6+
use Illuminate\Support\Str;
7+
use SolutionForest\InspireCms\InspireCmsConfig;
8+
use SolutionForest\InspireCms\Support\Base\BaseMigration;
9+
10+
return new class extends BaseMigration
11+
{
12+
/**
13+
* Run the migrations.
14+
*/
15+
public function up(): void
16+
{
17+
$tableNames = $this->getTableNames();
18+
$spatiePermissionTableNames = config('permission.table_names');
19+
$cmsUserMorphType = app(InspireCmsConfig::getUserModelClass())->getMorphClass();
20+
21+
$tmpUserTableName = $tableNames['user'] . '_tmp';
22+
23+
$userData = collect(DB::table($tableNames['user'])->get())
24+
->map(function ($user, $index) {
25+
$user->tmp_uuid = $user->id ?? (string) Str::uuid7();
26+
$user->tmp_id = $index + 1; // Assuming 'id' starts from 1 and is sequential
27+
return $user;
28+
});
29+
30+
//region Update cms user table
31+
32+
// 1. Create tmp table
33+
Schema::create($tmpUserTableName, function (Blueprint $table) {
34+
$table->unsignedBigInteger('id');
35+
$table->uuid('uuid');
36+
$table->string('name');
37+
$table->string('email');
38+
$table->string('preferred_language');
39+
$table->string('avatar')->nullable();
40+
$table->string('password');
41+
$table->rememberToken();
42+
$table->integer('failed_login_attempt')->default(0)->unsigned();
43+
$table->timestamp('last_lockouted_at')->nullable();
44+
$table->timestamp('last_password_change_date')->nullable();
45+
$table->timestamp('last_logged_in_at')->nullable();
46+
$table->timestamp('email_confirmed_at')->nullable();
47+
$table->timestamps();
48+
});
49+
50+
// 2. Fill tmp table with existing data
51+
foreach ($userData as $user) {
52+
DB::table($tmpUserTableName)->insert([
53+
'id' => $user->tmp_id,
54+
'uuid' => $user->tmp_uuid,
55+
'name' => $user->name,
56+
'email' => $user->email,
57+
'preferred_language' => $user->preferred_language ?? 'en',
58+
'avatar' => $user->avatar ?? null,
59+
'password' => $user->password ?? '',
60+
'failed_login_attempt' => $user->failed_login_attempt ?? 0,
61+
'last_lockouted_at' => $user->last_lockouted_at ?? null,
62+
'last_password_change_date' => $user->last_password_change_date ?? null,
63+
'last_logged_in_at' => $user->last_logged_in_at ?? null,
64+
'email_confirmed_at' => $user->email_confirmed_at ?? null,
65+
'created_at' => $user->created_at ?? now(),
66+
'updated_at' => $user->updated_at ?? now(),
67+
]);
68+
}
69+
70+
// 3. Drop old table
71+
Schema::dropIfExists($tableNames['user']);
72+
73+
// 4. Rename tmp table to original name
74+
Schema::rename($tmpUserTableName, $tableNames['user']);
75+
76+
// 5. Add back index and primary key etc
77+
Schema::table($tableNames['user'], function (Blueprint $table) {
78+
$table->primary('id');
79+
$table->index('uuid');
80+
$table->unique('email');
81+
});
82+
83+
//endregion Update cms user table
84+
85+
//region Update cms user activities table
86+
87+
// 1. Create tmp table
88+
Schema::dropIfExists($tableNames['user_login_activity']);
89+
90+
// 2. Create new table with updated structure
91+
92+
Schema::create($tableNames['user_login_activity'], function (Blueprint $table) {
93+
$table->id();
94+
$table->unsignedBigInteger('user_id');
95+
96+
$table->timestamp('last_logged_in_at_utc')->nullable();
97+
$table->timestamp('last_logged_out_at_utc')->nullable();
98+
$table->string('ip_address');
99+
100+
$table->index('user_id');
101+
$table->index('ip_address');
102+
});
103+
//endregiosn Update cms user activities table
104+
105+
//region Update table has 'author' relationship
106+
$tablesHasAuthor = [
107+
$tableNames['content'],
108+
$tableNames['content_version'],
109+
$tableNames['media_asset'],
110+
$tableNames['import'],
111+
$tableNames['export'],
112+
];
113+
foreach ($tablesHasAuthor as $hasAuthorTableName) {
114+
foreach ($userData as $user) {
115+
DB::table($hasAuthorTableName)
116+
->where('author_type', $cmsUserMorphType)
117+
->where('author_id', $user->tmp_uuid)
118+
->update(['author_id' => $user->tmp_id]);
119+
}
120+
Schema::table($hasAuthorTableName, function (Blueprint $table) {
121+
$table->unsignedBigInteger('author_id')->nullable()->change();
122+
});
123+
}
124+
//endregion
125+
126+
//region Update 'owner' relationship
127+
$tablesHasOwner = [
128+
$tableNames['content_lock'],
129+
];
130+
131+
foreach ($tablesHasOwner as $hasOwnerTableName) {
132+
foreach ($userData as $user) {
133+
DB::table($hasOwnerTableName)
134+
->where('owner_type', $cmsUserMorphType)
135+
->where('owner_id', $user->tmp_uuid)
136+
->update(['owner_id' => $user->tmp_id]);
137+
}
138+
Schema::table($hasOwnerTableName, function (Blueprint $table) {
139+
$table->unsignedBigInteger('owner_id')->nullable()->change();
140+
});
141+
}
142+
143+
//endregion
144+
145+
146+
//region Update Spatie permissions tables
147+
foreach ($userData as $user) {
148+
DB::table($spatiePermissionTableNames['model_has_roles'])
149+
->where('model_type', $cmsUserMorphType)
150+
->where('model_id', $user->tmp_uuid)
151+
->update(['model_id' => $user->tmp_id]);
152+
DB::table($spatiePermissionTableNames['model_has_permissions'])
153+
->where('model_type', $cmsUserMorphType)
154+
->where('model_id', $user->tmp_uuid)
155+
->update(['model_id' => $user->tmp_id]);
156+
}
157+
//endregion Update Spatie permissions tables
158+
}
159+
160+
public function down(): void
161+
{
162+
$tableNames = $this->getTableNames();
163+
$spatiePermissionTableNames = config('permission.table_names');
164+
$cmsUserMorphType = app(InspireCmsConfig::getUserModelClass())->getMorphClass();
165+
166+
$tmpUserTableName = $tableNames['user'] . '_tmp';
167+
168+
$userData = collect(DB::table($tableNames['user'])->get())
169+
->map(function ($user) {
170+
$user->tmp_uuid = $user->uuid ?? (string) Str::uuid7();
171+
$user->tmp_id = $user->id;
172+
return $user;
173+
});
174+
175+
//region Rollback Spatie permissions tables changes
176+
foreach ($userData as $user) {
177+
DB::table($spatiePermissionTableNames['model_has_roles'])
178+
->where('model_type', $cmsUserMorphType)
179+
->where('model_id', $user->tmp_id)
180+
->update(['model_id' => $user->tmp_uuid]);
181+
DB::table($spatiePermissionTableNames['model_has_permissions'])
182+
->where('model_type', $cmsUserMorphType)
183+
->where('model_id', $user->tmp_id)
184+
->update(['model_id' => $user->tmp_uuid]);
185+
}
186+
//endregion Rollback Spatie permissions tables changes
187+
188+
//region Update table has 'author' relationship
189+
$tablesHasAuthor = [
190+
$tableNames['content'],
191+
$tableNames['content_version'],
192+
$tableNames['media_asset'],
193+
$tableNames['import'],
194+
$tableNames['export'],
195+
];
196+
foreach ($tablesHasAuthor as $hasAuthorTableName) {
197+
Schema::table($hasAuthorTableName, function (Blueprint $table) {
198+
$table->uuid('author_id')->nullable()->change();
199+
});
200+
foreach ($userData as $user) {
201+
DB::table($hasAuthorTableName)
202+
->where('author_type', $cmsUserMorphType)
203+
->where('author_id', $user->tmp_id)
204+
->update(['author_id' => $user->tmp_uuid]);
205+
}
206+
}
207+
//endregion
208+
209+
//region Update 'owner' relationship
210+
$tablesHasOwner = [
211+
$tableNames['content_lock'],
212+
];
213+
foreach ($tablesHasOwner as $hasOwnerTableName) {
214+
Schema::table($hasOwnerTableName, function (Blueprint $table) {
215+
$table->uuid('owner_id')->nullable()->change();
216+
});
217+
foreach ($userData as $user) {
218+
DB::table($hasOwnerTableName)
219+
->where('owner_type', $cmsUserMorphType)
220+
->where('owner_id', $user->tmp_id)
221+
->update(['owner_id' => $user->tmp_uuid]);
222+
}
223+
}
224+
225+
//endregion
226+
227+
228+
//region Rollback 'cms_user_login_activities' changes
229+
230+
// 1. Drop table
231+
Schema::dropIfExists($tableNames['user_login_activity']);
232+
233+
// 2. Create table
234+
Schema::create($tableNames['user_login_activity'], function (Blueprint $table) {
235+
$table->id();
236+
$table->uuid('user_id');
237+
238+
$table->timestamp('last_logged_in_at_utc')->nullable();
239+
$table->timestamp('last_logged_out_at_utc')->nullable();
240+
$table->string('ip_address');
241+
242+
$table->index('user_id');
243+
$table->index('ip_address');
244+
});
245+
246+
247+
//endregion Rollback 'cms_user_login_activities' changes
248+
249+
250+
//region Rollback 'cms_users' changes
251+
252+
// 1. Create tmp table
253+
Schema::create($tmpUserTableName, function (Blueprint $table) {
254+
$table->uuid('id');
255+
$table->string('name');
256+
$table->string('email');
257+
$table->string('preferred_language');
258+
$table->string('avatar')->nullable();
259+
$table->string('password');
260+
$table->rememberToken();
261+
$table->integer('failed_login_attempt')->default(0)->unsigned();
262+
$table->timestamp('last_lockouted_at')->nullable();
263+
$table->timestamp('last_password_change_date')->nullable();
264+
$table->timestamp('last_logged_in_at')->nullable();
265+
$table->timestamp('email_confirmed_at')->nullable();
266+
$table->timestamps();
267+
});
268+
269+
270+
// 2. Fill tmp table with existing data
271+
foreach ($userData as $user) {
272+
DB::table($tmpUserTableName)->insert([
273+
'id' => $user->tmp_uuid,
274+
'name' => $user->name,
275+
'email' => $user->email,
276+
'preferred_language' => $user->preferred_language ?? 'en',
277+
'avatar' => $user->avatar ?? null,
278+
'password' => $user->password ?? '',
279+
'failed_login_attempt' => $user->failed_login_attempt ?? 0,
280+
'last_lockouted_at' => $user->last_lockouted_at ?? null,
281+
'last_password_change_date' => $user->last_password_change_date ?? null,
282+
'last_logged_in_at' => $user->last_logged_in_at ?? null,
283+
'email_confirmed_at' => $user->email_confirmed_at ?? null,
284+
'created_at' => now(),
285+
'updated_at' => now(),
286+
]);
287+
}
288+
289+
// 3. Drop old table
290+
Schema::dropIfExists($tableNames['user']);
291+
292+
// 4. Rename tmp table to original name
293+
Schema::rename($tmpUserTableName, $tableNames['user']);
294+
295+
// 5. Add back index and primary key etc
296+
Schema::table($tableNames['user'], function (Blueprint $table) {
297+
$table->primary('id');
298+
$table->unique('email');
299+
});
300+
301+
//endregion Rollback 'cms_users' changes
302+
303+
}
304+
305+
private function getTableNames()
306+
{
307+
return [
308+
'field_groupable' => $this->prefix . 'field_groupables',
309+
'content_version' => $this->prefix . 'content_versions',
310+
'content_publish_version' => $this->prefix . 'content_publish_version',
311+
'content_path' => $this->prefix . 'content_paths',
312+
'content_route' => $this->prefix . 'content_routes',
313+
'content' => $this->prefix . 'content',
314+
'content_lock' => $this->prefix . 'content_locks',
315+
'document_type' => $this->prefix . 'document_types',
316+
'document_type_inheritance' => $this->prefix . 'document_type_inheritance',
317+
'allowed_document_type' => $this->prefix . 'document_type_allowed_document_type',
318+
'language' => $this->prefix . 'languages',
319+
'user_login_activity' => $this->prefix . 'user_login_activities',
320+
'user' => $this->prefix . 'users',
321+
'template' => $this->prefix . 'templates',
322+
'templatable' => $this->prefix . 'templateable',
323+
'content_web_setting' => $this->prefix . 'content_web_settings',
324+
'sitemap' => $this->prefix . 'sitemaps',
325+
'navigation' => $this->prefix . 'navigation',
326+
'key_value' => $this->prefix . 'key_values',
327+
'media_asset' => $this->prefix . 'media_assets',
328+
'import' => $this->prefix . 'imports',
329+
'export' => $this->prefix . 'exports',
330+
];
331+
}
332+
};

database/migrations/update_notification_table_for_uuid_users.php.stub

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/Commands/InstallRequirePacakgesCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ class InstallRequirePacakgesCommand extends Command
1212
{
1313
public function handle(): int
1414
{
15+
$this->publishNotificationDataTable();
1516
$this->installFieldGroupPackage();
1617
$this->installSpatiePackages();
1718
$this->installSupportPackage();
18-
$this->publishNotificationDataTable();
1919

2020
return static::SUCCESS;
2121
}

0 commit comments

Comments
 (0)