| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- <?php
- namespace Tests\Integration;
- use App\Http\Controllers\admin\User as UserController;
- use Illuminate\Cache\ArrayStore;
- use Illuminate\Cache\Repository as CacheRepository;
- use Illuminate\Config\Repository;
- use Illuminate\Database\Capsule\Manager;
- use Illuminate\Database\Eloquent\Model;
- use Illuminate\Database\Schema\Blueprint;
- use Illuminate\Foundation\Application;
- use Illuminate\Http\Request;
- use Illuminate\Support\Facades\Cache;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Facade;
- use Illuminate\Translation\ArrayLoader;
- use Illuminate\Translation\Translator;
- use Illuminate\Validation\Factory;
- use PHPUnit\Framework\Attributes\DataProvider;
- use PHPUnit\Framework\TestCase;
- class UserPasswordValidationTest extends TestCase
- {
- private Application $app;
- protected function setUp(): void
- {
- Facade::clearResolvedInstances();
- Model::clearBootedModels();
- require_once dirname(__DIR__, 2) . '/app/Helpers/helpers.php';
- $this->app = new Application(dirname(__DIR__, 2));
- $this->app->instance('config', new Repository(['app' => ['locale' => 'zh']]));
- $this->app->instance('cache', new CacheRepository(new ArrayStore()));
- $translator = new Translator(new ArrayLoader(), 'zh');
- $this->app->instance('translator', $translator);
- $this->app->instance('validator', new Factory($translator, $this->app));
- $this->app->instance(\Illuminate\Contracts\Routing\ResponseFactory::class, new \Tests\Support\JsonResponseFactory());
- Request::macro('validate', function (array $rules) {
- return app('validator')->make($this->all(), $rules)->validate();
- });
- Facade::setFacadeApplication($this->app);
- $db = new Manager($this->app);
- $db->addConnection(['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => 'bot_']);
- $db->setAsGlobal();
- $db->bootEloquent();
- $this->app->instance('db', $db->getDatabaseManager());
- $db->schema()->create('users', function (Blueprint $t) {
- $t->id(); $t->string('member_id'); $t->string('password'); $t->string('payment_password');
- $t->string('language')->default('zh'); $t->integer('recharge_channel_group_id')->default(1); $t->timestamps();
- });
- $db->schema()->create('user_session', function (Blueprint $t) {
- $t->id(); $t->string('user_id'); $t->string('token'); $t->integer('expire_time');
- });
- DB::table('users')->insert([
- 'member_id' => '100001', 'password' => create_password('old-login'),
- 'payment_password' => password_hash('old-funds', PASSWORD_DEFAULT),
- ]);
- foreach (['100001' => 'target-token', '100002' => 'other-token'] as $member => $token) {
- DB::table('user_session')->insert(['user_id' => (string) $member, 'token' => $token, 'expire_time' => time() + 3600]);
- Cache::put('token_user_' . $token, ['member_id' => (string) $member]);
- }
- }
- protected function tearDown(): void
- {
- DB::disconnect();
- Facade::clearResolvedInstances();
- Model::clearBootedModels();
- parent::tearDown();
- }
- private function reset(array $params): array
- {
- $this->app->instance('request', Request::create('/admin/user/setPassword', 'POST', $params + ['member_id' => '100001']));
- return (new UserController())->setPassword()->getData(true);
- }
- private function credentials(): array
- {
- return (array) DB::table('users')->where('member_id', '100001')->first();
- }
- public function test_invalid_passwords_are_rejected_before_either_credential_or_session_is_changed(): void
- {
- $before = $this->credentials();
- foreach (['password', 'payment_password'] as $field) {
- foreach (['12345', str_repeat('a', 17), str_repeat('密', 17), 123456, array_fill(0, 6, 'a'), false] as $invalid) {
- $params = ['password' => 'valid-login', 'payment_password' => 'valid-funds'];
- $params[$field] = $invalid;
- $body = $this->reset($params);
- $this->assertSame(-3, $body['code']);
- $this->assertSame($before, $this->credentials());
- $this->assertSame(2, DB::table('user_session')->count());
- $this->assertTrue(Cache::has('token_user_target-token'));
- }
- }
- }
- public static function validPasswords(): array
- {
- return [
- 'minimum' => ['abc123'],
- 'maximum' => [str_repeat('a', 16)],
- 'leading zeroes' => ['000000'],
- 'symbols' => ['abc!@#123'],
- 'unicode character limit' => [str_repeat('密', 16)],
- ];
- }
- #[DataProvider('validPasswords')]
- public function test_valid_boundaries_preserve_hashing_and_login_session_invalidation(string $password): void
- {
- $this->assertSame(0, $this->reset(['password' => $password, 'payment_password' => $password])['code']);
- $row = $this->credentials();
- $this->assertSame(create_password($password), $row['password']);
- $this->assertTrue(password_verify($password, $row['payment_password']));
- $this->assertSame(0, DB::table('user_session')->where('user_id', '100001')->count());
- $this->assertFalse(Cache::has('token_user_target-token'));
- $this->assertSame(1, DB::table('user_session')->where('user_id', '100002')->count());
- $this->assertTrue(Cache::has('token_user_other-token'));
- }
- public function test_resetting_only_funds_password_preserves_login_password_and_session(): void
- {
- $this->assertSame(0, $this->reset(['payment_password' => 'new-funds'])['code']);
- $row = $this->credentials();
- $this->assertSame(create_password('old-login'), $row['password']);
- $this->assertTrue(password_verify('new-funds', $row['payment_password']));
- $this->assertSame(2, DB::table('user_session')->count());
- $this->assertTrue(Cache::has('token_user_target-token'));
- }
- public function test_omitted_or_empty_passwords_remain_unchanged(): void
- {
- $before = $this->credentials();
- foreach ([[], ['password' => null, 'payment_password' => null], ['password' => '', 'payment_password' => '']] as $params) {
- $this->assertSame(0, $this->reset($params)['code']);
- $this->assertSame($before, $this->credentials());
- $this->assertSame(2, DB::table('user_session')->count());
- $this->assertTrue(Cache::has('token_user_target-token'));
- }
- }
- }
|