mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-28 17:01:16 +00:00
320 lines
11 KiB
PHP
320 lines
11 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\Category;
|
|
use App\Models\User;
|
|
use App\Models\UserExcludedCategory;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
use Spatie\Permission\Models\Permission;
|
|
use Spatie\Permission\Models\Role;
|
|
use Tests\TestCase;
|
|
|
|
final class UserExcludedCategoryTest extends TestCase
|
|
{
|
|
private User $user;
|
|
|
|
private Role $userRole;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
// Use in-memory SQLite database for test isolation
|
|
config(['database.default' => 'sqlite', 'database.connections.sqlite.database' => ':memory:']);
|
|
DB::purge();
|
|
DB::reconnect();
|
|
|
|
// Create minimal tables needed for testing
|
|
$this->createTestTables();
|
|
|
|
// Create the basic User role with all view permissions
|
|
$this->userRole = Role::firstOrCreate(
|
|
['name' => 'User'],
|
|
[
|
|
'guard_name' => 'web',
|
|
'addyears' => 0,
|
|
'apirequests' => 10,
|
|
'downloadrequests' => 5,
|
|
'defaultinvites' => 0,
|
|
'isdefault' => 1,
|
|
'donation' => 0,
|
|
'canpreview' => 0,
|
|
]
|
|
);
|
|
|
|
// Create view permissions
|
|
$permissions = [
|
|
'view console', 'view movies', 'view audio', 'view pc',
|
|
'view tv', 'view adult', 'view books', 'view other',
|
|
];
|
|
foreach ($permissions as $permName) {
|
|
Permission::firstOrCreate(['name' => $permName, 'guard_name' => 'web']);
|
|
}
|
|
$this->userRole->syncPermissions($permissions);
|
|
|
|
// Create a test user
|
|
$this->user = $this->createTestUser($this->userRole->id);
|
|
$this->user->assignRole($this->userRole);
|
|
|
|
// Give user direct permissions
|
|
foreach ($permissions as $permName) {
|
|
$this->user->givePermissionTo($permName);
|
|
}
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
DB::disconnect();
|
|
parent::tearDown();
|
|
}
|
|
|
|
private function createTestTables(): void
|
|
{
|
|
// Users table (complete schema like RoleUpgradeTest)
|
|
DB::statement('CREATE TABLE IF NOT EXISTS users (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
username VARCHAR(255) NOT NULL,
|
|
email VARCHAR(255) NOT NULL UNIQUE,
|
|
password VARCHAR(255) NOT NULL,
|
|
roles_id INTEGER DEFAULT 1,
|
|
rolechangedate DATETIME NULL,
|
|
pending_roles_id INTEGER NULL,
|
|
pending_role_start_date DATETIME NULL,
|
|
api_token VARCHAR(255) NULL,
|
|
grabs INTEGER DEFAULT 0,
|
|
invites INTEGER DEFAULT 0,
|
|
notes TEXT DEFAULT "",
|
|
movieview INTEGER DEFAULT 1,
|
|
xxxview INTEGER DEFAULT 0,
|
|
musicview INTEGER DEFAULT 1,
|
|
consoleview INTEGER DEFAULT 1,
|
|
bookview INTEGER DEFAULT 1,
|
|
gameview INTEGER DEFAULT 1,
|
|
verified INTEGER DEFAULT 1,
|
|
can_post INTEGER DEFAULT 1,
|
|
rate_limit INTEGER DEFAULT 60,
|
|
email_verified_at DATETIME NULL,
|
|
created_at DATETIME NULL,
|
|
updated_at DATETIME NULL,
|
|
deleted_at DATETIME NULL
|
|
)');
|
|
|
|
// Roles table
|
|
DB::statement('CREATE TABLE IF NOT EXISTS roles (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name VARCHAR(255) NOT NULL,
|
|
guard_name VARCHAR(255) NOT NULL DEFAULT "web",
|
|
addyears INTEGER DEFAULT 0,
|
|
apirequests INTEGER DEFAULT 10,
|
|
downloadrequests INTEGER DEFAULT 5,
|
|
defaultinvites INTEGER DEFAULT 0,
|
|
isdefault INTEGER DEFAULT 0,
|
|
donation INTEGER DEFAULT 0,
|
|
canpreview INTEGER DEFAULT 0,
|
|
created_at DATETIME,
|
|
updated_at DATETIME
|
|
)');
|
|
|
|
// Permissions table
|
|
DB::statement('CREATE TABLE IF NOT EXISTS permissions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name VARCHAR(255) NOT NULL,
|
|
guard_name VARCHAR(255) NOT NULL DEFAULT "web",
|
|
created_at DATETIME,
|
|
updated_at DATETIME
|
|
)');
|
|
|
|
// Model has permissions
|
|
DB::statement('CREATE TABLE IF NOT EXISTS model_has_permissions (
|
|
permission_id INTEGER NOT NULL,
|
|
model_type VARCHAR(255) NOT NULL,
|
|
model_id INTEGER NOT NULL,
|
|
PRIMARY KEY (permission_id, model_id, model_type)
|
|
)');
|
|
|
|
// Model has roles
|
|
DB::statement('CREATE TABLE IF NOT EXISTS model_has_roles (
|
|
role_id INTEGER NOT NULL,
|
|
model_type VARCHAR(255) NOT NULL,
|
|
model_id INTEGER NOT NULL,
|
|
PRIMARY KEY (role_id, model_id, model_type)
|
|
)');
|
|
|
|
// Role has permissions
|
|
DB::statement('CREATE TABLE IF NOT EXISTS role_has_permissions (
|
|
permission_id INTEGER NOT NULL,
|
|
role_id INTEGER NOT NULL,
|
|
PRIMARY KEY (permission_id, role_id)
|
|
)');
|
|
|
|
// Root categories table
|
|
DB::statement('CREATE TABLE IF NOT EXISTS root_categories (
|
|
id INTEGER PRIMARY KEY,
|
|
title VARCHAR(255) NOT NULL,
|
|
status INTEGER DEFAULT 1,
|
|
disablepreview INTEGER DEFAULT 0,
|
|
created_at DATETIME,
|
|
updated_at DATETIME
|
|
)');
|
|
|
|
// Categories table
|
|
DB::statement('CREATE TABLE IF NOT EXISTS categories (
|
|
id INTEGER PRIMARY KEY,
|
|
title VARCHAR(255) NOT NULL,
|
|
root_categories_id INTEGER NOT NULL,
|
|
status INTEGER DEFAULT 1,
|
|
description VARCHAR(255),
|
|
disablepreview INTEGER DEFAULT 0,
|
|
minsizetoformrelease INTEGER DEFAULT 0,
|
|
maxsizetoformrelease INTEGER DEFAULT 0
|
|
)');
|
|
|
|
// User excluded categories table
|
|
DB::statement('CREATE TABLE IF NOT EXISTS user_excluded_categories (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
users_id INTEGER NOT NULL,
|
|
categories_id INTEGER NOT NULL,
|
|
created_at DATETIME,
|
|
updated_at DATETIME,
|
|
UNIQUE(users_id, categories_id)
|
|
)');
|
|
|
|
// Insert test root categories
|
|
DB::table('root_categories')->insert([
|
|
['id' => 2000, 'title' => 'Movies', 'status' => 1],
|
|
['id' => 5000, 'title' => 'TV', 'status' => 1],
|
|
]);
|
|
|
|
// Insert test subcategories
|
|
DB::table('categories')->insert([
|
|
['id' => 2030, 'title' => 'SD', 'root_categories_id' => 2000, 'status' => 1],
|
|
['id' => 2040, 'title' => 'HD', 'root_categories_id' => 2000, 'status' => 1],
|
|
['id' => 2070, 'title' => 'DVD', 'root_categories_id' => 2000, 'status' => 1],
|
|
['id' => 5030, 'title' => 'SD', 'root_categories_id' => 5000, 'status' => 1],
|
|
['id' => 5040, 'title' => 'HD', 'root_categories_id' => 5000, 'status' => 1],
|
|
]);
|
|
}
|
|
|
|
private function createTestUser(int $roleId): User
|
|
{
|
|
$username = 'testuser_'.Str::random(5);
|
|
$email = 'test_'.Str::random(5).'@example.com';
|
|
$apiToken = Str::random(64);
|
|
|
|
// Insert directly to bypass observers
|
|
DB::table('users')->insert([
|
|
'username' => $username,
|
|
'email' => $email,
|
|
'password' => bcrypt('password'),
|
|
'api_token' => $apiToken,
|
|
'roles_id' => $roleId,
|
|
'verified' => 1,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
return User::where('email', $email)->first();
|
|
}
|
|
|
|
public function test_user_can_exclude_subcategories(): void
|
|
{
|
|
// Exclude Movies->DVD category
|
|
$this->user->syncExcludedCategories([2070]);
|
|
|
|
$exclusions = $this->user->excludedCategories()->pluck('categories_id')->toArray();
|
|
|
|
$this->assertContains(2070, $exclusions);
|
|
$this->assertCount(1, $exclusions);
|
|
}
|
|
|
|
public function test_user_can_exclude_multiple_subcategories(): void
|
|
{
|
|
// Exclude Movies->DVD and Movies->SD
|
|
$this->user->syncExcludedCategories([2070, 2030]);
|
|
|
|
$exclusions = $this->user->excludedCategories()->pluck('categories_id')->toArray();
|
|
|
|
$this->assertContains(2070, $exclusions);
|
|
$this->assertContains(2030, $exclusions);
|
|
$this->assertCount(2, $exclusions);
|
|
}
|
|
|
|
public function test_sync_excluded_categories_replaces_existing(): void
|
|
{
|
|
// First set DVD
|
|
$this->user->syncExcludedCategories([2070]);
|
|
|
|
// Then sync to HD only
|
|
$this->user->syncExcludedCategories([2040]);
|
|
|
|
$exclusions = $this->user->excludedCategories()->pluck('categories_id')->toArray();
|
|
|
|
$this->assertNotContains(2070, $exclusions);
|
|
$this->assertContains(2040, $exclusions);
|
|
$this->assertCount(1, $exclusions);
|
|
}
|
|
|
|
public function test_get_category_exclusion_by_id_includes_user_exclusions(): void
|
|
{
|
|
// Exclude Movies->DVD subcategory
|
|
$this->user->syncExcludedCategories([2070]);
|
|
|
|
$exclusions = User::getCategoryExclusionById($this->user->id);
|
|
|
|
$this->assertContains(2070, $exclusions);
|
|
}
|
|
|
|
public function test_cached_category_exclusions_are_invalidated_when_syncing(): void
|
|
{
|
|
$this->user->syncExcludedCategories([2070]);
|
|
|
|
$this->assertContains(2070, User::getCachedCategoryExclusionById($this->user->id));
|
|
|
|
$this->user->syncExcludedCategories([2040]);
|
|
|
|
$exclusions = User::getCachedCategoryExclusionById($this->user->id);
|
|
|
|
$this->assertNotContains(2070, $exclusions);
|
|
$this->assertContains(2040, $exclusions);
|
|
}
|
|
|
|
public function test_cached_category_exclusions_are_invalidated_when_rows_change_directly(): void
|
|
{
|
|
Cache::put(User::categoryExclusionCacheKey($this->user->id), [2070], 300);
|
|
|
|
UserExcludedCategory::create([
|
|
'users_id' => $this->user->id,
|
|
'categories_id' => 2040,
|
|
]);
|
|
|
|
$this->assertNull(Cache::get(User::categoryExclusionCacheKey($this->user->id)));
|
|
}
|
|
|
|
public function test_clearing_exclusions_works(): void
|
|
{
|
|
// First add exclusions
|
|
$this->user->syncExcludedCategories([2070, 2030]);
|
|
|
|
// Then clear them
|
|
$this->user->syncExcludedCategories([]);
|
|
|
|
$exclusions = $this->user->excludedCategories()->pluck('categories_id')->toArray();
|
|
|
|
$this->assertEmpty($exclusions);
|
|
}
|
|
|
|
public function test_excluded_categories_relationship(): void
|
|
{
|
|
UserExcludedCategory::create([
|
|
'users_id' => $this->user->id,
|
|
'categories_id' => 2070,
|
|
]);
|
|
|
|
$this->assertCount(1, $this->user->excludedCategories);
|
|
$this->assertEquals(2070, $this->user->excludedCategories->first()->categories_id);
|
|
}
|
|
}
|