95 lines
3.9 KiB
PHP
95 lines
3.9 KiB
PHP
<?php
|
|
|
|
use cPad\Plugins\Forum\Services\Security\AccountFarmDetector;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
uses(Tests\TestCase::class);
|
|
|
|
it('flags repeated posting patterns across multiple accounts', function () {
|
|
config()->set('forum_bot_protection.account_farm', [
|
|
'window_minutes' => 10,
|
|
'register_attempt_threshold' => 10,
|
|
'same_ip_users_threshold' => 5,
|
|
'same_fingerprint_users_threshold' => 3,
|
|
'same_pattern_users_threshold' => 2,
|
|
'register_attempt_penalty' => 50,
|
|
'same_ip_penalty' => 35,
|
|
'same_fingerprint_penalty' => 40,
|
|
'same_pattern_penalty' => 45,
|
|
]);
|
|
|
|
Schema::dropIfExists('forum_posts');
|
|
Schema::dropIfExists('forum_bot_device_fingerprints');
|
|
Schema::dropIfExists('forum_bot_logs');
|
|
|
|
Schema::create('forum_bot_logs', function (Blueprint $table): void {
|
|
$table->id();
|
|
$table->unsignedBigInteger('user_id')->nullable();
|
|
$table->string('ip_address', 45)->nullable();
|
|
$table->string('action', 80);
|
|
$table->unsignedTinyInteger('risk_score')->default(0);
|
|
$table->string('decision', 20)->default('allow');
|
|
$table->json('metadata')->nullable();
|
|
$table->timestamp('created_at')->nullable();
|
|
});
|
|
|
|
Schema::create('forum_bot_device_fingerprints', function (Blueprint $table): void {
|
|
$table->id();
|
|
$table->unsignedBigInteger('user_id')->nullable();
|
|
$table->string('fingerprint', 128)->nullable();
|
|
$table->timestamp('first_seen')->nullable();
|
|
$table->timestamp('last_seen')->nullable();
|
|
$table->unsignedTinyInteger('risk_score')->default(0);
|
|
$table->string('user_agent_hash', 64)->nullable();
|
|
$table->timestamps();
|
|
});
|
|
|
|
Schema::create('forum_posts', function (Blueprint $table): void {
|
|
$table->id();
|
|
$table->unsignedBigInteger('thread_id')->nullable();
|
|
$table->unsignedBigInteger('topic_id')->nullable();
|
|
$table->string('source_ip_hash', 64)->nullable();
|
|
$table->unsignedBigInteger('user_id')->nullable();
|
|
$table->longText('content')->nullable();
|
|
$table->string('content_hash', 64)->nullable();
|
|
$table->boolean('is_edited')->default(false);
|
|
$table->timestamp('edited_at')->nullable();
|
|
$table->unsignedInteger('spam_score')->default(0);
|
|
$table->unsignedInteger('quality_score')->default(0);
|
|
$table->unsignedInteger('ai_spam_score')->default(0);
|
|
$table->unsignedInteger('ai_toxicity_score')->default(0);
|
|
$table->unsignedInteger('behavior_score')->default(0);
|
|
$table->unsignedInteger('link_score')->default(0);
|
|
$table->integer('learning_score')->default(0);
|
|
$table->unsignedInteger('risk_score')->default(0);
|
|
$table->integer('trust_modifier')->default(0);
|
|
$table->boolean('flagged')->default(false);
|
|
$table->string('flagged_reason')->nullable();
|
|
$table->boolean('moderation_checked')->default(false);
|
|
$table->string('moderation_status')->nullable();
|
|
$table->json('moderation_labels')->nullable();
|
|
$table->json('moderation_meta')->nullable();
|
|
$table->timestamp('last_ai_scan_at')->nullable();
|
|
$table->timestamps();
|
|
$table->softDeletes();
|
|
});
|
|
|
|
$hash = hash('sha256', 'buy cheap backlinks now');
|
|
|
|
foreach ([1, 2, 3] as $userId) {
|
|
DB::table('forum_posts')->insert([
|
|
'user_id' => $userId,
|
|
'content' => 'buy cheap backlinks now',
|
|
'content_hash' => $hash,
|
|
'created_at' => now()->subMinutes(2),
|
|
'updated_at' => now()->subMinutes(2),
|
|
]);
|
|
}
|
|
|
|
$result = app(AccountFarmDetector::class)->analyze(1, '203.0.113.10', null, 'forum_reply_create');
|
|
|
|
expect($result['score'])->toBe(45)
|
|
->and($result['reasons'])->toContain('Posting patterns or repeated content overlap across multiple accounts.');
|
|
}); |