mirror of
https://github.com/grocy/grocy.git
synced 2025-04-29 01:32:38 +00:00
Revise session handling to prepare API authentication via token
This commit is contained in:
parent
0c85342404
commit
eae5b8bad9
22
app.php
22
app.php
@ -3,16 +3,13 @@
|
||||
use \Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use \Psr\Http\Message\ResponseInterface as Response;
|
||||
|
||||
use \Grocy\Middleware\SessionAuthMiddleware;
|
||||
use \Grocy\Helpers\UrlManager;
|
||||
use \Grocy\Services\ApplicationService;
|
||||
use \Grocy\Controllers\LoginController;
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
require_once __DIR__ . '/data/config.php';
|
||||
|
||||
// Setup base application
|
||||
if (PHP_SAPI !== 'cli')
|
||||
{
|
||||
$appContainer = new \Slim\Container([
|
||||
'settings' => [
|
||||
'displayErrorDetails' => true,
|
||||
@ -22,25 +19,20 @@ if (PHP_SAPI !== 'cli')
|
||||
{
|
||||
return new \Slim\Views\Blade(__DIR__ . '/views', __DIR__ . '/data/viewcache');
|
||||
},
|
||||
'LoginControllerInstance' => function($container)
|
||||
{
|
||||
return new LoginController($container, 'grocy_session');
|
||||
},
|
||||
'UrlManager' => function($container)
|
||||
{
|
||||
return new UrlManager(BASE_URL);
|
||||
}
|
||||
]);
|
||||
|
||||
$app = new \Slim\App($appContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
$app = new \Slim\App();
|
||||
$app->add(\pavlakis\cli\CliRequest::class);
|
||||
}
|
||||
|
||||
// Add session handling if this is not a demo installation
|
||||
$applicationService = new ApplicationService();
|
||||
if (!$applicationService->IsDemoInstallation())
|
||||
if (PHP_SAPI === 'cli')
|
||||
{
|
||||
$app->add(SessionAuthMiddleware::class);
|
||||
$app->add(\pavlakis\cli\CliRequest::class);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/routes.php';
|
||||
|
@ -9,13 +9,15 @@ use \Grocy\Services\DemoDataGeneratorService;
|
||||
|
||||
class LoginController extends BaseController
|
||||
{
|
||||
public function __construct(\Slim\Container $container)
|
||||
public function __construct(\Slim\Container $container, string $sessionCookieName)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->SessionService = new SessionService();
|
||||
$this->SessionCookieName = $sessionCookieName;
|
||||
}
|
||||
|
||||
protected $SessionService;
|
||||
protected $SessionCookieName;
|
||||
|
||||
public function ProcessLogin(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
@ -25,7 +27,7 @@ class LoginController extends BaseController
|
||||
if ($postParams['username'] === HTTP_USER && $postParams['password'] === HTTP_PASSWORD)
|
||||
{
|
||||
$sessionKey = $this->SessionService->CreateSession();
|
||||
setcookie('grocy_session', $sessionKey, time() + 31536000); // Cookie expires in 1 year, but session validity is up to SessionService
|
||||
setcookie($this->SessionCookieName, $sessionKey, time() + 31536000); // Cookie expires in 1 year, but session validity is up to SessionService
|
||||
|
||||
return $response->withRedirect($this->AppContainer->UrlManager->ConstructUrl('/'));
|
||||
}
|
||||
@ -47,7 +49,7 @@ class LoginController extends BaseController
|
||||
|
||||
public function Logout(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
$this->SessionService->RemoveSession($_COOKIE['grocy_session']);
|
||||
$this->SessionService->RemoveSession($_COOKIE[$this->SessionCookieName]);
|
||||
return $response->withRedirect($this->AppContainer->UrlManager->ConstructUrl('/'));
|
||||
}
|
||||
|
||||
@ -66,4 +68,9 @@ class LoginController extends BaseController
|
||||
|
||||
return $response->withRedirect($this->AppContainer->UrlManager->ConstructUrl('/stockoverview'));
|
||||
}
|
||||
|
||||
public function GetSessionCookieName()
|
||||
{
|
||||
return $this->SessionCookieName;
|
||||
}
|
||||
}
|
||||
|
@ -61,3 +61,14 @@ function GetClassConstants($className)
|
||||
$r = new ReflectionClass($className);
|
||||
return $r->getConstants();
|
||||
}
|
||||
|
||||
function RandomString($length, $allowedChars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
||||
{
|
||||
$randomString = '';
|
||||
for ($i = 0; $i < $length; $i++)
|
||||
{
|
||||
$randomString .= $allowedChars[rand(0, strlen($allowedChars) - 1)];
|
||||
}
|
||||
|
||||
return $randomString;
|
||||
}
|
||||
|
@ -2,11 +2,16 @@
|
||||
|
||||
namespace Grocy\Middleware;
|
||||
|
||||
use \Grocy\Services\ApplicationService;
|
||||
|
||||
class BaseMiddleware
|
||||
{
|
||||
public function __construct(\Slim\Container $container) {
|
||||
public function __construct(\Slim\Container $container)
|
||||
{
|
||||
$this->AppContainer = $container;
|
||||
$this->ApplicationService = new ApplicationService();
|
||||
}
|
||||
|
||||
protected $AppContainer;
|
||||
protected $ApplicationService;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ class CliMiddleware extends BaseMiddleware
|
||||
}
|
||||
else
|
||||
{
|
||||
$response = $next($request, $response, $next);
|
||||
$response = $next($request, $response);
|
||||
return $response->withHeader('Content-Type', 'text/plain');
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ class JsonMiddleware extends BaseMiddleware
|
||||
{
|
||||
public function __invoke(\Slim\Http\Request $request, \Slim\Http\Response $response, callable $next)
|
||||
{
|
||||
$response = $next($request, $response, $next);
|
||||
$response = $next($request, $response);
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
}
|
||||
|
@ -6,19 +6,27 @@ use \Grocy\Services\SessionService;
|
||||
|
||||
class SessionAuthMiddleware extends BaseMiddleware
|
||||
{
|
||||
public function __construct(\Slim\Container $container, string $sessionCookieName)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->SessionCookieName = $sessionCookieName;
|
||||
}
|
||||
|
||||
protected $SessionCookieName;
|
||||
|
||||
public function __invoke(\Slim\Http\Request $request, \Slim\Http\Response $response, callable $next)
|
||||
{
|
||||
$route = $request->getAttribute('route');
|
||||
$routeName = $route->getName();
|
||||
|
||||
if ($routeName === 'root')
|
||||
if ($routeName === 'root' || $this->ApplicationService->IsDemoInstallation())
|
||||
{
|
||||
$response = $next($request, $response);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sessionService = new SessionService();
|
||||
if ((!isset($_COOKIE['grocy_session']) || !$sessionService->IsValidSession($_COOKIE['grocy_session'])) && $routeName !== 'login')
|
||||
if ((!isset($_COOKIE[$this->SessionCookieName]) || !$sessionService->IsValidSession($_COOKIE[$this->SessionCookieName])) && $routeName !== 'login')
|
||||
{
|
||||
$response = $response->withRedirect($this->AppContainer->UrlManager->ConstructUrl('/login'));
|
||||
}
|
||||
|
55
routes.php
55
routes.php
@ -2,48 +2,51 @@
|
||||
|
||||
use \Grocy\Middleware\JsonMiddleware;
|
||||
use \Grocy\Middleware\CliMiddleware;
|
||||
use \Grocy\Middleware\SessionAuthMiddleware;
|
||||
|
||||
$app->group('', function()
|
||||
{
|
||||
// Base route
|
||||
$app->get('/', 'Grocy\Controllers\LoginController:Root')->setName('root');
|
||||
$this->get('/', 'LoginControllerInstance:Root')->setName('root');
|
||||
|
||||
// Login routes
|
||||
$app->get('/login', 'Grocy\Controllers\LoginController:LoginPage')->setName('login');
|
||||
$app->post('/login', 'Grocy\Controllers\LoginController:ProcessLogin')->setName('login');
|
||||
$app->get('/logout', 'Grocy\Controllers\LoginController:Logout');
|
||||
$this->get('/login', 'LoginControllerInstance:LoginPage')->setName('login');
|
||||
$this->post('/login', 'LoginControllerInstance:ProcessLogin')->setName('login');
|
||||
$this->get('/logout', 'LoginControllerInstance:Logout');
|
||||
|
||||
// Stock routes
|
||||
$app->get('/stockoverview', 'Grocy\Controllers\StockController:Overview');
|
||||
$app->get('/purchase', 'Grocy\Controllers\StockController:Purchase');
|
||||
$app->get('/consume', 'Grocy\Controllers\StockController:Consume');
|
||||
$app->get('/inventory', 'Grocy\Controllers\StockController:Inventory');
|
||||
$this->get('/stockoverview', 'Grocy\Controllers\StockController:Overview');
|
||||
$this->get('/purchase', 'Grocy\Controllers\StockController:Purchase');
|
||||
$this->get('/consume', 'Grocy\Controllers\StockController:Consume');
|
||||
$this->get('/inventory', 'Grocy\Controllers\StockController:Inventory');
|
||||
|
||||
$app->get('/products', 'Grocy\Controllers\StockController:ProductsList');
|
||||
$app->get('/product/{productId}', 'Grocy\Controllers\StockController:ProductEditForm');
|
||||
$this->get('/products', 'Grocy\Controllers\StockController:ProductsList');
|
||||
$this->get('/product/{productId}', 'Grocy\Controllers\StockController:ProductEditForm');
|
||||
|
||||
$app->get('/locations', 'Grocy\Controllers\StockController:LocationsList');
|
||||
$app->get('/location/{locationId}', 'Grocy\Controllers\StockController:LocationEditForm');
|
||||
$this->get('/locations', 'Grocy\Controllers\StockController:LocationsList');
|
||||
$this->get('/location/{locationId}', 'Grocy\Controllers\StockController:LocationEditForm');
|
||||
|
||||
$app->get('/quantityunits', 'Grocy\Controllers\StockController:QuantityUnitsList');
|
||||
$app->get('/quantityunit/{quantityunitId}', 'Grocy\Controllers\StockController:QuantityUnitEditForm');
|
||||
$this->get('/quantityunits', 'Grocy\Controllers\StockController:QuantityUnitsList');
|
||||
$this->get('/quantityunit/{quantityunitId}', 'Grocy\Controllers\StockController:QuantityUnitEditForm');
|
||||
|
||||
$app->get('/shoppinglist', 'Grocy\Controllers\StockController:ShoppingList');
|
||||
$app->get('/shoppinglistitem/{itemId}', 'Grocy\Controllers\StockController:ShoppingListItemEditForm');
|
||||
$this->get('/shoppinglist', 'Grocy\Controllers\StockController:ShoppingList');
|
||||
$this->get('/shoppinglistitem/{itemId}', 'Grocy\Controllers\StockController:ShoppingListItemEditForm');
|
||||
|
||||
|
||||
// Habit routes
|
||||
$app->get('/habitsoverview', 'Grocy\Controllers\HabitsController:Overview');
|
||||
$app->get('/habittracking', 'Grocy\Controllers\HabitsController:TrackHabitExecution');
|
||||
$this->get('/habitsoverview', 'Grocy\Controllers\HabitsController:Overview');
|
||||
$this->get('/habittracking', 'Grocy\Controllers\HabitsController:TrackHabitExecution');
|
||||
|
||||
$app->get('/habits', 'Grocy\Controllers\HabitsController:HabitsList');
|
||||
$app->get('/habit/{habitId}', 'Grocy\Controllers\HabitsController:HabitEditForm');
|
||||
$this->get('/habits', 'Grocy\Controllers\HabitsController:HabitsList');
|
||||
$this->get('/habit/{habitId}', 'Grocy\Controllers\HabitsController:HabitEditForm');
|
||||
|
||||
// Batterry routes
|
||||
$app->get('/batteriesoverview', 'Grocy\Controllers\BatteriesController:Overview');
|
||||
$app->get('/batterytracking', 'Grocy\Controllers\BatteriesController:TrackChargeCycle');
|
||||
|
||||
$app->get('/batteries', 'Grocy\Controllers\BatteriesController:BatteriesList');
|
||||
$app->get('/battery/{batteryId}', 'Grocy\Controllers\BatteriesController:BatteryEditForm');
|
||||
$this->get('/batteriesoverview', 'Grocy\Controllers\BatteriesController:Overview');
|
||||
$this->get('/batterytracking', 'Grocy\Controllers\BatteriesController:TrackChargeCycle');
|
||||
|
||||
$this->get('/batteries', 'Grocy\Controllers\BatteriesController:BatteriesList');
|
||||
$this->get('/battery/{batteryId}', 'Grocy\Controllers\BatteriesController:BatteryEditForm');
|
||||
})->add(new SessionAuthMiddleware($appContainer, $appContainer->LoginControllerInstance->GetSessionCookieName()));
|
||||
|
||||
$app->group('/api', function()
|
||||
{
|
||||
@ -65,7 +68,7 @@ $app->group('/api', function()
|
||||
|
||||
$this->get('/batteries/track-charge-cycle/{batteryId}', 'Grocy\Controllers\BatteriesApiController:TrackChargeCycle');
|
||||
$this->get('/batteries/get-battery-details/{batteryId}', 'Grocy\Controllers\BatteriesApiController:BatteryDetails');
|
||||
})->add(JsonMiddleware::class);
|
||||
})->add(new SessionAuthMiddleware($appContainer, $appContainer->LoginControllerInstance->GetSessionCookieName()))->add(JsonMiddleware::class);
|
||||
|
||||
$app->group('/cli', function()
|
||||
{
|
||||
|
@ -24,7 +24,7 @@ class SessionService extends BaseService
|
||||
*/
|
||||
public function CreateSession()
|
||||
{
|
||||
$newSessionKey = uniqid() . uniqid() . uniqid();
|
||||
$newSessionKey = $this->GenerateSessionKey();
|
||||
|
||||
$sessionRow = $this->Database->sessions()->createRow(array(
|
||||
'session_key' => $newSessionKey,
|
||||
@ -39,4 +39,9 @@ class SessionService extends BaseService
|
||||
{
|
||||
$this->Database->sessions()->where('session_key', $sessionKey)->delete();
|
||||
}
|
||||
|
||||
private function GenerateSessionKey()
|
||||
{
|
||||
return RandomString(50);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user