Skip to content

Commit 615afe0

Browse files
author
A. Van Driessche
authored
Merge pull request #2364 from codeeu/transmission-personal-data
Transmission personal data
2 parents 68300ea + 5506c42 commit 615afe0

5 files changed

Lines changed: 252 additions & 0 deletions
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace App\Console\Commands;
4+
5+
use App\Jobs\ProcessUserDeletion;
6+
use App\User;
7+
use Illuminate\Console\Command;
8+
use Illuminate\Support\Facades\Hash;
9+
10+
class SoftDeleteUsersWithoutConsent extends Command
11+
{
12+
protected $signature = 'users:delete-without-consent';
13+
protected $description = 'Delete users who have not given consent and transfer their data to legacy user';
14+
15+
public function handle()
16+
{
17+
$this->info('Creating or verifying legacy user...');
18+
19+
// Create legacy user if it doesn't exist
20+
User::firstOrCreate(
21+
['id' => 1000000],
22+
[
23+
'firstname' => 'Codeweek Legacy User',
24+
'lastname' => 'Codeweek Legacy',
25+
'username' => 'codeweek-legacy',
26+
'password' => Hash::make('some-secure-password-' . time()),
27+
'email' => 'legacy@codeweek.eu',
28+
'country_iso' => 'BE',
29+
'remember_token' => '5Pb4APP0CkOmQFzDtR960OlkdreLev2tvfUiywDawyJOmKDvFb3bmOAWlUL6',
30+
'privacy' => 1,
31+
'email_display' => 'legacy@codeweek.eu',
32+
'receive_emails' => 0,
33+
'approved' => 1,
34+
'magic_key' => 2520090911,
35+
'consent_given_at' => now(),
36+
'future_consent_given_at' => now(),
37+
'email_verified_at' => now(),
38+
'created_at' => now(),
39+
'updated_at' => now()
40+
]
41+
);
42+
43+
$this->info('Starting to process users without consent...');
44+
45+
// Get users without consent in chunks to avoid memory issues
46+
User::whereNull('consent_given_at')
47+
->where('id', '!=', 1000000) // Exclude the legacy user
48+
->chunkById(100, function ($users) {
49+
foreach ($users as $user) {
50+
ProcessUserDeletion::dispatch($user->id);
51+
$this->info("Dispatched deletion job for user ID: {$user->id}");
52+
}
53+
});
54+
55+
$this->info('All deletion jobs have been dispatched. Check the queue worker logs for progress.');
56+
}
57+
}

app/Jobs/ProcessUserDeletion.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace App\Jobs;
4+
5+
use App\Excellence;
6+
use App\Participation;
7+
use App\User;
8+
use App\Event;
9+
use Illuminate\Bus\Queueable;
10+
use Illuminate\Contracts\Queue\ShouldQueue;
11+
use Illuminate\Foundation\Bus\Dispatchable;
12+
use Illuminate\Queue\InteractsWithQueue;
13+
use Illuminate\Queue\SerializesModels;
14+
use Illuminate\Support\Facades\DB;
15+
use Illuminate\Support\Facades\Log;
16+
17+
class ProcessUserDeletion implements ShouldQueue
18+
{
19+
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
20+
21+
protected $userId;
22+
protected $legacyUserId = 1000000;
23+
24+
public function __construct($userId)
25+
{
26+
$this->userId = $userId;
27+
}
28+
29+
/**
30+
* @throws \Exception
31+
*/
32+
public function handle()
33+
{
34+
try {
35+
DB::beginTransaction();
36+
37+
Log::info("Processing deletion for user ID: {$this->userId}");
38+
39+
// Update events creator_id
40+
Event::where('creator_id', $this->userId)
41+
->update(['creator_id' => $this->legacyUserId]);
42+
43+
// Update events approved_by
44+
Event::where('approved_by', $this->userId)
45+
->update(['approved_by' => $this->legacyUserId]);
46+
47+
// Hard delete the user
48+
User::where('id', $this->userId)->forceDelete();
49+
50+
DB::commit();
51+
Log::info("Successfully deleted user ID: {$this->userId}");
52+
53+
} catch (\Exception $e) {
54+
DB::rollBack();
55+
Log::error("Error processing user ID: {$this->userId}", [
56+
'error' => $e->getMessage(),
57+
'trace' => $e->getTraceAsString()
58+
]);
59+
throw $e;
60+
}
61+
}
62+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration {
8+
/**
9+
* Run the migrations.
10+
*/
11+
public function up(): void
12+
{
13+
if (!Schema::hasTable('failed_jobs')) {
14+
Schema::create('failed_jobs', function (Blueprint $table) {
15+
$table->id();
16+
$table->string('uuid')->unique();
17+
$table->text('connection');
18+
$table->text('queue');
19+
$table->longText('payload');
20+
$table->longText('exception');
21+
$table->timestamp('failed_at')->useCurrent();
22+
});
23+
};
24+
}
25+
26+
/**
27+
* Reverse the migrations.
28+
*/
29+
public function down(): void
30+
{
31+
Schema::dropIfExists('failed_jobs');
32+
}
33+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::table('events', function (Blueprint $table) {
15+
$table->index('approved_by');
16+
});
17+
}
18+
19+
/**
20+
* Reverse the migrations.
21+
*/
22+
public function down(): void
23+
{
24+
25+
Schema::table('events', function (Blueprint $table) {
26+
$table->dropIndex(['approved_by']);
27+
});
28+
}
29+
};
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
-- INSERT INTO `codeweek_prod`.`users` (`id`, `firstname`, `lastname`, `username`, `password`, `email`, `country_iso`, `remember_token`, `created_at`, `updated_at`, `privacy`, `email_display`, `receive_emails`, `approved`, `magic_key`, `consent_given_at`, `future_consent_given_at`, `email_verified_at`) VALUES (1000000, 'Codeweek Legacy User', 'Codeweek Legacy', 'codeweek-legacy', '$2y$10$zcr85hlNx0U1aKpLtpsoKeAuPeSh1U9TxDY/A045m0y.5eXARsFg6', 'legacy@codeweek.eu', 'BE', '5Pb4APP0CkOmQFzDtR960OlkdreLev2tvfUiywDawyJOmKDvFb3bmOAWlUL6', now(), now(), 1, 'legacy@codeweek.eu', 0, 1, 2520090911, now(), now(), now());
2+
3+
DROP TABLE IF EXISTS users_to_delete;
4+
-- Create temporary table with users to process
5+
CREATE TEMPORARY TABLE users_to_delete AS
6+
SELECT id
7+
FROM users
8+
WHERE consent_given_at IS NULL
9+
LIMIT 1000; -- Process in chunks of 1000
10+
11+
-- Add index to improve performance
12+
ALTER TABLE users_to_delete ADD INDEX (id);
13+
14+
START TRANSACTION;
15+
-- Update events creator_id
16+
UPDATE events e
17+
INNER JOIN users_to_delete u ON e.creator_id = u.id
18+
SET e.creator_id = 1000000;
19+
COMMIT;
20+
21+
START TRANSACTION;
22+
-- Update events approved_by
23+
UPDATE events e
24+
INNER JOIN users_to_delete u ON e.approved_by = u.id
25+
SET e.approved_by = 1000000;
26+
COMMIT;
27+
28+
START TRANSACTION;
29+
-- Update participations
30+
UPDATE participations p
31+
INNER JOIN users_to_delete u ON p.user_id = u.id
32+
SET p.user_id = 1000000;
33+
COMMIT;
34+
35+
START TRANSACTION;
36+
-- Update excellences
37+
UPDATE excellences e
38+
INNER JOIN users_to_delete u ON e.user_id = u.id
39+
SET e.user_id = 1000000;
40+
COMMIT;
41+
42+
START TRANSACTION;
43+
-- Update model_has_roles
44+
UPDATE model_has_roles m
45+
INNER JOIN users_to_delete u ON m.model_id = u.id
46+
SET m.model_id = 1000000;
47+
COMMIT;
48+
49+
START TRANSACTION;
50+
-- Update leading_teacher_expertise_user
51+
UPDATE leading_teacher_expertise_user l
52+
INNER JOIN users_to_delete u ON l.user_id = u.id
53+
SET l.user_id = 1000000;
54+
COMMIT;
55+
56+
START TRANSACTION;
57+
-- Soft delete the users
58+
UPDATE users u
59+
INNER JOIN users_to_delete d ON u.id = d.id
60+
SET u.deleted_at = '2024-12-13 17:07:24',
61+
u.updated_at = '2024-12-13 17:07:24';
62+
COMMIT;
63+
64+
-- Delete processed users
65+
DELETE FROM users
66+
WHERE id IN (SELECT id FROM users_to_delete);
67+
68+
-- Clean up
69+
DROP TABLE IF EXISTS users_to_delete;
70+
71+
-- Repeat the process for the next batch by running this script again until no more users are found

0 commit comments

Comments
 (0)