Skip to content

Commit b267b08

Browse files
committed
Added dbAuth middleware
1 parent 431c3d6 commit b267b08

File tree

10 files changed

+111
-28
lines changed

10 files changed

+111
-28
lines changed

api.php

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5075,7 +5075,9 @@ private function getAuthorizationCredentials(ServerRequestInterface $request): s
50755075
public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
50765076
{
50775077
if (session_status() == PHP_SESSION_NONE) {
5078-
session_start();
5078+
if (!headers_sent()) {
5079+
session_start();
5080+
}
50795081
}
50805082
$credentials = $this->getAuthorizationCredentials($request);
50815083
if ($credentials) {
@@ -5199,6 +5201,73 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
51995201
}
52005202
}
52015203

5204+
// file: src/Tqdev/PhpCrudApi/Middleware/DbAuthMiddleware.php
5205+
5206+
class DbAuthMiddleware extends Middleware
5207+
{
5208+
private $reflection;
5209+
private $db;
5210+
5211+
public function __construct(Router $router, Responder $responder, array $properties, ReflectionService $reflection, GenericDB $db)
5212+
{
5213+
parent::__construct($router, $responder, $properties);
5214+
$this->reflection = $reflection;
5215+
$this->db = $db;
5216+
}
5217+
5218+
public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
5219+
{
5220+
if (session_status() == PHP_SESSION_NONE) {
5221+
if (!headers_sent()) {
5222+
session_start();
5223+
}
5224+
}
5225+
$path = RequestUtils::getPathSegment($request, 1);
5226+
$method = $request->getMethod();
5227+
if ($method == 'POST' && $path == 'login') {
5228+
$body = $request->getParsedBody();
5229+
$username = isset($body->username) ? $body->username : '';
5230+
$password = isset($body->password) ? $body->password : '';
5231+
$tableName = $this->getProperty('usersTable', 'users');
5232+
$table = $this->reflection->getTable($tableName);
5233+
$usernameColumnName = $this->getProperty('usernameColumn', 'username');
5234+
$usernameColumn = $table->getColumn($usernameColumnName);
5235+
$passwordColumnName = $this->getProperty('passwordColumn', 'password');
5236+
$passwordColumn = $table->getColumn($passwordColumnName);
5237+
$condition = new ColumnCondition($usernameColumn, 'eq', $username);
5238+
$columnNames = $table->getColumnNames();
5239+
$users = $this->db->selectAll($table, $columnNames, $condition, [], 0, -1);
5240+
foreach ($users as $user) {
5241+
if (password_verify($password, $user[$passwordColumnName]) == 1) {
5242+
if (!headers_sent()) {
5243+
session_regenerate_id(true);
5244+
}
5245+
unset($user[$passwordColumnName]);
5246+
$_SESSION['user'] = $user;
5247+
return $this->responder->success($user);
5248+
}
5249+
}
5250+
return $this->responder->error(ErrorCode::AUTHENTICATION_FAILED, $username);
5251+
}
5252+
if ($method == 'POST' && $path == 'logout') {
5253+
if (isset($_SESSION['user'])) {
5254+
$user = $_SESSION['user'];
5255+
unset($_SESSION['user']);
5256+
session_destroy();
5257+
return $this->responder->success($user);
5258+
}
5259+
return $this->responder->error(ErrorCode::AUTHENTICATION_REQUIRED, '');
5260+
}
5261+
if (!isset($_SESSION['user']) || !$_SESSION['user']) {
5262+
$authenticationMode = $this->getProperty('mode', 'required');
5263+
if ($authenticationMode == 'required') {
5264+
return $this->responder->error(ErrorCode::AUTHENTICATION_REQUIRED, '');
5265+
}
5266+
}
5267+
return $next->handle($request);
5268+
}
5269+
}
5270+
52025271
// file: src/Tqdev/PhpCrudApi/Middleware/FirewallMiddleware.php
52035272

52045273
class FirewallMiddleware extends Middleware
@@ -5468,7 +5537,9 @@ private function getAuthorizationToken(ServerRequestInterface $request): string
54685537
public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
54695538
{
54705539
if (session_status() == PHP_SESSION_NONE) {
5471-
session_start();
5540+
if (!headers_sent()) {
5541+
session_start();
5542+
}
54725543
}
54735544
$token = $this->getAuthorizationToken($request);
54745545
if ($token) {
@@ -7289,6 +7360,9 @@ public function __construct(Config $config)
72897360
case 'jwtAuth':
72907361
new JwtAuthMiddleware($router, $responder, $properties);
72917362
break;
7363+
case 'dbAuth':
7364+
new DbAuthMiddleware($router, $responder, $properties, $reflection, $db);
7365+
break;
72927366
case 'validation':
72937367
new ValidationMiddleware($router, $responder, $properties, $reflection);
72947368
break;

src/Tqdev/PhpCrudApi/Api.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Tqdev\PhpCrudApi\Middleware\BasicAuthMiddleware;
2020
use Tqdev\PhpCrudApi\Middleware\CorsMiddleware;
2121
use Tqdev\PhpCrudApi\Middleware\CustomizationMiddleware;
22+
use Tqdev\PhpCrudApi\Middleware\DbAuthMiddleware;
2223
use Tqdev\PhpCrudApi\Middleware\FirewallMiddleware;
2324
use Tqdev\PhpCrudApi\Middleware\IpAddressMiddleware;
2425
use Tqdev\PhpCrudApi\Middleware\JoinLimitsMiddleware;
@@ -68,6 +69,9 @@ public function __construct(Config $config)
6869
case 'jwtAuth':
6970
new JwtAuthMiddleware($router, $responder, $properties);
7071
break;
72+
case 'dbAuth':
73+
new DbAuthMiddleware($router, $responder, $properties, $reflection, $db);
74+
break;
7175
case 'validation':
7276
new ValidationMiddleware($router, $responder, $properties, $reflection);
7377
break;

src/Tqdev/PhpCrudApi/Middleware/BasicAuthMiddleware.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ private function getAuthorizationCredentials(ServerRequestInterface $request): s
7979
public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
8080
{
8181
if (session_status() == PHP_SESSION_NONE) {
82-
session_start();
82+
if (!headers_sent()) {
83+
session_start();
84+
}
8385
}
8486
$credentials = $this->getAuthorizationCredentials($request);
8587
if ($credentials) {

src/Tqdev/PhpCrudApi/Middleware/JwtAuthMiddleware.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ private function getAuthorizationToken(ServerRequestInterface $request): string
125125
public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
126126
{
127127
if (session_status() == PHP_SESSION_NONE) {
128-
session_start();
128+
if (!headers_sent()) {
129+
session_start();
130+
}
129131
}
130132
$token = $this->getAuthorizationToken($request);
131133
if ($token) {

tests/config/base.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
'username' => 'php-crud-api',
55
'password' => 'php-crud-api',
66
'controllers' => 'records,columns,cache,openapi,geojson',
7-
'middlewares' => 'cors,jwtAuth,basicAuth,authorization,validation,ipAddress,sanitation,multiTenancy,pageLimits,joinLimits,customization',
7+
'middlewares' => 'cors,dbAuth,jwtAuth,basicAuth,authorization,validation,ipAddress,sanitation,multiTenancy,pageLimits,joinLimits,customization',
8+
'dbAuth.mode' => 'optional',
89
'jwtAuth.mode' => 'optional',
910
'jwtAuth.time' => '1538207605',
1011
'jwtAuth.secret' => 'axpIrCGNGqxzx2R9dtXLIPUSqPo778uhb8CA0F4Hx',
1112
'basicAuth.mode' => 'optional',
1213
'basicAuth.passwordFile' => __DIR__ . DIRECTORY_SEPARATOR . '.htpasswd',
1314
'authorization.tableHandler' => function ($operation, $tableName) {
14-
return !($tableName == 'invisibles' && !isset($_SESSION['claims']['name']) && empty($_SESSION['username']));
15+
return !($tableName == 'invisibles' && !isset($_SESSION['claims']['name']) && empty($_SESSION['username']) && empty($_SESSION['user']));
1516
},
1617
'authorization.columnHandler' => function ($operation, $tableName, $columnName) {
1718
return !($columnName == 'invisible');

tests/fixtures/blog_mysql.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ CREATE TABLE `users` (
9494

9595
INSERT INTO `users` (`username`, `password`, `location`) VALUES
9696
('user1', 'pass1', NULL),
97-
('user2', 'pass2', NULL);
97+
('user2', '$2y$10$cg7/nswxVZ0cmVIsMB/pVOh1OfcHScBJGq7Xu4KF9dFEQgRZ8HWe.', NULL);
9898

9999
DROP TABLE IF EXISTS `countries`;
100100
CREATE TABLE `countries` (

tests/fixtures/blog_pgsql.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ INSERT INTO "tags" ("name", "is_important") VALUES
232232

233233
INSERT INTO "users" ("username", "password", "location") VALUES
234234
('user1', 'pass1', NULL),
235-
('user2', 'pass2', NULL);
235+
('user2', '$2y$10$cg7/nswxVZ0cmVIsMB/pVOh1OfcHScBJGq7Xu4KF9dFEQgRZ8HWe.', NULL);
236236

237237
--
238238
-- Data for Name: countries; Type: TABLE DATA; Schema: public; Owner: postgres

tests/fixtures/blog_sqlsrv.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ GO
337337

338338
INSERT [users] ([username], [password], [location]) VALUES (N'user1', N'pass1', NULL)
339339
GO
340-
INSERT [users] ([username], [password], [location]) VALUES (N'user2', N'pass2', NULL)
340+
INSERT [users] ([username], [password], [location]) VALUES (N'user2', N'$2y$10$cg7/nswxVZ0cmVIsMB/pVOh1OfcHScBJGq7Xu4KF9dFEQgRZ8HWe.', NULL)
341341
GO
342342

343343
INSERT [countries] ([name], [shape]) VALUES (N'Left', N'POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))')
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
GET /geojson/users/1
1+
GET /geojson/users/1?exclude=password
22
===
33
200
44
Content-Type: application/json
5-
Content-Length: 132
5+
Content-Length: 109
66

7-
{"type":"Feature","id":1,"properties":{"username":"user1","password":"testtest2"},"geometry":{"type":"Point","coordinates":[30,20]}}
7+
{"type":"Feature","id":1,"properties":{"username":"user1"},"geometry":{"type":"Point","coordinates":[30,20]}}
88
===
9-
GET /geojson/users/2
9+
GET /geojson/users/2?exclude=password
1010
===
1111
200
1212
Content-Type: application/json
13-
Content-Length: 94
13+
Content-Length: 75
1414

15-
{"type":"Feature","id":2,"properties":{"username":"user2","password":"pass2"},"geometry":null}
15+
{"type":"Feature","id":2,"properties":{"username":"user2"},"geometry":null}
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,39 @@
1-
GET /geojson/users
1+
GET /geojson/users?exclude=password
22
===
33
200
44
Content-Type: application/json
5-
Content-Length: 269
5+
Content-Length: 227
66

7-
{"type":"FeatureCollection","features":[{"type":"Feature","id":1,"properties":{"username":"user1","password":"testtest2"},"geometry":{"type":"Point","coordinates":[30,20]}},{"type":"Feature","id":2,"properties":{"username":"user2","password":"pass2"},"geometry":null}]}
7+
{"type":"FeatureCollection","features":[{"type":"Feature","id":1,"properties":{"username":"user1"},"geometry":{"type":"Point","coordinates":[30,20]}},{"type":"Feature","id":2,"properties":{"username":"user2"},"geometry":null}]}
88
===
9-
GET /geojson/users?geometry=location&include=username
9+
GET /geojson/users?exclude=password&geometry=location
1010
===
1111
200
1212
Content-Type: application/json
1313
Content-Length: 227
1414

1515
{"type":"FeatureCollection","features":[{"type":"Feature","id":1,"properties":{"username":"user1"},"geometry":{"type":"Point","coordinates":[30,20]}},{"type":"Feature","id":2,"properties":{"username":"user2"},"geometry":null}]}
1616
===
17-
GET /geojson/users?geometry=notlocation
17+
GET /geojson/users?exclude=password&geometry=notlocation
1818
===
1919
200
2020
Content-Type: application/json
21-
Content-Length: 277
21+
Content-Length: 235
2222

23-
{"type":"FeatureCollection","features":[{"type":"Feature","id":1,"properties":{"username":"user1","password":"testtest2","location":"POINT(30 20)"},"geometry":null},{"type":"Feature","id":2,"properties":{"username":"user2","password":"pass2","location":null},"geometry":null}]}
23+
{"type":"FeatureCollection","features":[{"type":"Feature","id":1,"properties":{"username":"user1","location":"POINT(30 20)"},"geometry":null},{"type":"Feature","id":2,"properties":{"username":"user2","location":null},"geometry":null}]}
2424
===
25-
GET /geojson/users?page=1,1
25+
GET /geojson/users?exclude=password&page=1,1
2626
===
2727
200
2828
Content-Type: application/json
29-
Content-Length: 186
29+
Content-Length: 163
3030

31-
{"type":"FeatureCollection","features":[{"type":"Feature","id":1,"properties":{"username":"user1","password":"testtest2"},"geometry":{"type":"Point","coordinates":[30,20]}}],"results":2}
31+
{"type":"FeatureCollection","features":[{"type":"Feature","id":1,"properties":{"username":"user1"},"geometry":{"type":"Point","coordinates":[30,20]}}],"results":2}
3232
===
33-
GET /geojson/users?bbox=29.99,19.99,30.01,20.01
33+
GET /geojson/users?exclude=password&bbox=29.99,19.99,30.01,20.01
3434
===
3535
200
3636
Content-Type: application/json
37-
Content-Length: 174
37+
Content-Length: 151
3838

39-
{"type":"FeatureCollection","features":[{"type":"Feature","id":1,"properties":{"username":"user1","password":"testtest2"},"geometry":{"type":"Point","coordinates":[30,20]}}]}
39+
{"type":"FeatureCollection","features":[{"type":"Feature","id":1,"properties":{"username":"user1"},"geometry":{"type":"Point","coordinates":[30,20]}}]}

0 commit comments

Comments
 (0)