diff --git a/src/Listeners/StoreSessionIP.php b/src/Listeners/StoreSessionIP.php new file mode 100644 index 0000000..ec3d77f --- /dev/null +++ b/src/Listeners/StoreSessionIP.php @@ -0,0 +1,20 @@ +eligibleForIPRestriction()) { + $driver->saveSessionIpAddress(); + } + } +} diff --git a/src/Listeners/StoreSessionUserAgent.php b/src/Listeners/StoreSessionUserAgent.php new file mode 100644 index 0000000..455d55e --- /dev/null +++ b/src/Listeners/StoreSessionUserAgent.php @@ -0,0 +1,20 @@ +eligibleForUserAgentRestriction()) { + $driver->saveSessionUserAgent(); + } + } +} diff --git a/src/Middlewares/FormViaHeaderMiddleware.php b/src/Middlewares/FormViaHeaderMiddleware.php index 2eff50d..9714bb1 100644 --- a/src/Middlewares/FormViaHeaderMiddleware.php +++ b/src/Middlewares/FormViaHeaderMiddleware.php @@ -1,5 +1,7 @@ paranoia->shouldCheckGeoRestriction()) { + if (! $this->paranoia->eligibleForGeoRestriction()) { return $next($request); } diff --git a/src/Middlewares/IPChangeRestrictionMiddleware.php b/src/Middlewares/IPChangeRestrictionMiddleware.php index baf9174..21ee008 100644 --- a/src/Middlewares/IPChangeRestrictionMiddleware.php +++ b/src/Middlewares/IPChangeRestrictionMiddleware.php @@ -15,7 +15,7 @@ public function __construct(protected Paranoia $paranoia) {} public function handle(Request $request, \Closure $next): mixed { - if (! $this->paranoia->shouldCheckIPRestriction()) { + if (! $this->paranoia->eligibleForIPRestriction()) { return $next($request); } diff --git a/src/Middlewares/UserAgentChangeRestrictionMiddleware.php b/src/Middlewares/UserAgentChangeRestrictionMiddleware.php index 3ea0c85..4038e7a 100644 --- a/src/Middlewares/UserAgentChangeRestrictionMiddleware.php +++ b/src/Middlewares/UserAgentChangeRestrictionMiddleware.php @@ -15,7 +15,7 @@ public function __construct(protected Paranoia $paranoia) {} public function handle(Request $request, \Closure $next): mixed { - if (! $this->paranoia->shouldCheckUserAgentRestriction()) { + if (! $this->paranoia->eligibleForUserAgentRestriction()) { return $next($request); } diff --git a/src/Paranoia.php b/src/Paranoia.php index 1fcaa2c..b0d889d 100644 --- a/src/Paranoia.php +++ b/src/Paranoia.php @@ -1,45 +1,57 @@ guard()->check(); + } + + public function eligibleForIPRestriction(): bool { - /** @var string */ - return config('session.table', 'sessions'); + return auth()->guard()->check(); } - public function shouldCheckGeoRestriction(): bool + public function eligibleForUserAgentRestriction(): bool { return auth()->guard()->check(); } - public function shouldCheckIPRestriction(): bool + public function isUsingBaseDriver(): bool + { + return $this->storage instanceof SessionStorageHandler; + } + + public function saveSessionIpAddress(): void { - return session()->getDefaultDriver() === 'database' && $this->getSessionTable() !== null && auth()->guard()->check(); + $this->storage->saveSessionIpAddress(session()->id()); } - public function shouldCheckUserAgentRestriction(): bool + public function saveSessionUserAgent(): void { - return session()->getDefaultDriver() === 'database' && $this->getSessionTable() !== null && auth()->guard()->check(); + $this->storage->saveSessionUserAgent(session()->id()); } public function getSessionIpAddress(): ?string { /** @var string|null */ - return DB::table($this->getSessionTable()) - ->where('id', session()->getId()) - ->value('ip_address'); + return $this->storage->getSavedIpAddress(session()->id()); } public function getSessionUserAgent(): ?string { /** @var string|null */ - return DB::table($this->getSessionTable()) - ->where('id', session()->getId()) - ->value('user_agent'); + return $this->storage->getSavedUserAgent(session()->id()); } } diff --git a/src/ParanoiaServiceProvider.php b/src/ParanoiaServiceProvider.php index 32930ec..00ba016 100644 --- a/src/ParanoiaServiceProvider.php +++ b/src/ParanoiaServiceProvider.php @@ -5,6 +5,7 @@ namespace Dentro\Paranoia; use Dentro\Paranoia\Providers\EventServiceProvider; +use Dentro\Paranoia\Storage\SessionStorageFactory; use Illuminate\Support\ServiceProvider; class ParanoiaServiceProvider extends ServiceProvider @@ -13,7 +14,20 @@ public function register(): void { $this->app->register(EventServiceProvider::class); - $this->app->bind(Paranoia::class, fn (): \Dentro\Paranoia\Paranoia => new Paranoia); + $this->app->bind(Paranoia::class, function (): \Dentro\Paranoia\Paranoia { + + /** @var string $sessionDriver */ + $sessionDriver = config('session.driver'); + $factory = (new SessionStorageFactory($sessionDriver)); + + if ($sessionDriver === 'database') { + /** @var string $tableName */ + $tableName = config('session.table'); + $factory->setSessionTableName($tableName); + } + + return new Paranoia($factory->build()); + }); $this->app->alias(Paranoia::class, 'paranoia'); $this->mergeConfigFrom(__DIR__.'/../config/paranoia.php', 'paranoia'); diff --git a/src/Providers/EventServiceProvider.php b/src/Providers/EventServiceProvider.php index 10439a7..c244f35 100644 --- a/src/Providers/EventServiceProvider.php +++ b/src/Providers/EventServiceProvider.php @@ -1,8 +1,12 @@ > */ protected array $listen = [ - GeoRestrictionViolationDetected::class => [ - // + Login::class => [ + StoreSessionIP::class, + StoreSessionUserAgent::class, ], ]; } diff --git a/src/Securities/SessionSecurity.php b/src/Securities/SessionSecurity.php deleted file mode 100644 index c92e04c..0000000 --- a/src/Securities/SessionSecurity.php +++ /dev/null @@ -1,36 +0,0 @@ -sessionTableName) + ->where('id', $sessionId) + ->value('ip_address'); + } + + public function getSavedUserAgent(string $sessionId): ?string + { + /** @var string|null */ + return DB::table($this->sessionTableName) + ->where('id', $sessionId) + ->value('user_agent'); + } + + /** + * @throws \Throwable + */ + public static function make(?string $tableName): SessionStorageDatabaseHandler + { + throw_if($tableName === null || $tableName === '' || $tableName === '0', new \InvalidArgumentException('Session table name is required for database driver')); + + /** @var string $tableName */ + return new self($tableName); + } +} diff --git a/src/Storage/SessionStorageFactory.php b/src/Storage/SessionStorageFactory.php new file mode 100644 index 0000000..7bd86e4 --- /dev/null +++ b/src/Storage/SessionStorageFactory.php @@ -0,0 +1,30 @@ +driver) { + 'database' => SessionStorageDatabaseHandler::make($this->sessionTableName), + default => SessionStorageHandler::make(), + }; + } + + public function setSessionTableName(string $sessionTableName): static + { + $this->sessionTableName = $sessionTableName; + + return $this; + } +} diff --git a/src/Storage/SessionStorageHandler.php b/src/Storage/SessionStorageHandler.php new file mode 100644 index 0000000..6e7f617 --- /dev/null +++ b/src/Storage/SessionStorageHandler.php @@ -0,0 +1,47 @@ +put('ip_address', request()->ip()); + } + + public function saveSessionUserAgent(string $sessionId): void + { + session()->put('user_agent', request()->ip()); + } + + /** + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function getSavedIpAddress(string $sessionId): ?string + { + return session()->get('ip_address') ?? null; + } + + /** + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function getSavedUserAgent(string $sessionId): ?string + { + return session()->get('user_agent') ?? null; + } + + /** + * @throws \Throwable + */ + public static function make(): SessionStorageHandler + { + return new self; + } +} diff --git a/tests/Units/GeoRestrictionTest.php b/tests/Units/GeoRestrictionTest.php index bc3e9ca..730959e 100644 --- a/tests/Units/GeoRestrictionTest.php +++ b/tests/Units/GeoRestrictionTest.php @@ -25,7 +25,7 @@ ); $mockedParanoia = mock(\Dentro\Paranoia\Paranoia::class); - $mockedParanoia->shouldReceive('shouldCheckGeoRestriction')->andReturn(true); + $mockedParanoia->shouldReceive('eligibleForGeoRestriction')->andReturn(true); Event::fake(GeoRestrictionViolationDetected::class); (new GeoRestrictionMiddleware($mockedParanoia))->handle($request, function (): void { @@ -49,7 +49,7 @@ ); $mockedParanoia = mock(\Dentro\Paranoia\Paranoia::class); - $mockedParanoia->shouldReceive('shouldCheckGeoRestriction')->andReturn(true); + $mockedParanoia->shouldReceive('eligibleForGeoRestriction')->andReturn(true); Event::fake(GeoRestrictionViolationDetected::class); (new GeoRestrictionMiddleware($mockedParanoia))->handle($request, function (): void { @@ -77,7 +77,7 @@ ); $mockedParanoia = mock(\Dentro\Paranoia\Paranoia::class); - $mockedParanoia->shouldReceive('shouldCheckGeoRestriction')->andReturn(true); + $mockedParanoia->shouldReceive('eligibleForGeoRestriction')->andReturn(true); try { Event::fake(GeoRestrictionViolationDetected::class); @@ -105,7 +105,7 @@ ); $mockedParanoia = mock(\Dentro\Paranoia\Paranoia::class); - $mockedParanoia->shouldReceive('shouldCheckGeoRestriction')->andReturn(true); + $mockedParanoia->shouldReceive('eligibleForGeoRestriction')->andReturn(true); try { Event::fake(GeoRestrictionViolationDetected::class); diff --git a/tests/Units/IPChangeRestrictionTest.php b/tests/Units/IPChangeRestrictionTest.php index b45d6b1..aa7a120 100644 --- a/tests/Units/IPChangeRestrictionTest.php +++ b/tests/Units/IPChangeRestrictionTest.php @@ -14,7 +14,7 @@ ); $mockedParanoia = mock(\Dentro\Paranoia\Paranoia::class); - $mockedParanoia->shouldReceive('shouldCheckIPRestriction')->andReturn(true); + $mockedParanoia->shouldReceive('eligibleForIPRestriction')->andReturn(true); $mockedParanoia->shouldReceive('getSessionIpAddress')->andReturn($sessionIp); try { @@ -42,7 +42,7 @@ function ($request): void { ); $mockedParanoia = mock(\Dentro\Paranoia\Paranoia::class); - $mockedParanoia->shouldReceive('shouldCheckIPRestriction')->andReturn(true); + $mockedParanoia->shouldReceive('eligibleForIPRestriction')->andReturn(true); $mockedParanoia->shouldReceive('getSessionIpAddress')->andReturn($sessionIp); (new IPChangeRestrictionMiddleware($mockedParanoia))->handle( diff --git a/tests/Units/UserAgentChangeRestrictionTest.php b/tests/Units/UserAgentChangeRestrictionTest.php index 10558bd..1a59759 100644 --- a/tests/Units/UserAgentChangeRestrictionTest.php +++ b/tests/Units/UserAgentChangeRestrictionTest.php @@ -14,7 +14,7 @@ ); $mockedParanoia = mock(\Dentro\Paranoia\Paranoia::class); - $mockedParanoia->shouldReceive('shouldCheckUserAgentRestriction')->andReturn(true); + $mockedParanoia->shouldReceive('eligibleForUserAgentRestriction')->andReturn(true); $mockedParanoia->shouldReceive('getSessionUserAgent')->andReturn($sessionAgent); try { @@ -47,7 +47,7 @@ function ($request): void { ); $mockedParanoia = mock(\Dentro\Paranoia\Paranoia::class); - $mockedParanoia->shouldReceive('shouldCheckUserAgentRestriction')->andReturn(true); + $mockedParanoia->shouldReceive('eligibleForUserAgentRestriction')->andReturn(true); $mockedParanoia->shouldReceive('getSessionUserAgent')->andReturn($sessionAgent); (new UserAgentChangeRestrictionMiddleware($mockedParanoia))->handle(