create-prisma-php-app 1.26.5 → 1.26.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bootstrap.php
CHANGED
|
@@ -35,7 +35,7 @@ function determineContentToInclude()
|
|
|
35
35
|
* ======================================
|
|
36
36
|
*/
|
|
37
37
|
$requestUri = $_SERVER['REQUEST_URI'];
|
|
38
|
-
$requestUri = empty($_SERVER['SCRIPT_URL']) ? uriExtractor($requestUri) : $requestUri;
|
|
38
|
+
$requestUri = empty($_SERVER['SCRIPT_URL']) ? trim(uriExtractor($requestUri)) : trim($requestUri);
|
|
39
39
|
/**
|
|
40
40
|
* ============ URI Path Handling ============
|
|
41
41
|
* The $uri variable now contains the URI path without query parameters and without the leading slash.
|
|
@@ -46,7 +46,7 @@ function determineContentToInclude()
|
|
|
46
46
|
*/
|
|
47
47
|
$scriptUrl = explode('?', $requestUri, 2)[0];
|
|
48
48
|
$pathname = $_SERVER['SCRIPT_URL'] ?? $scriptUrl;
|
|
49
|
-
$pathname =
|
|
49
|
+
$pathname = trim($pathname, '/');
|
|
50
50
|
$baseDir = APP_PATH;
|
|
51
51
|
$includePath = '';
|
|
52
52
|
$layoutsToInclude = [];
|
|
@@ -20,14 +20,35 @@ final class AuthConfig
|
|
|
20
20
|
public const ROLE_IDENTIFIER = 'role';
|
|
21
21
|
public const IS_ROLE_BASE = false;
|
|
22
22
|
public const IS_TOKEN_AUTO_REFRESH = false;
|
|
23
|
+
public const IS_ALL_ROUTES_PRIVATE = false;
|
|
23
24
|
|
|
24
25
|
/**
|
|
26
|
+
* This is the (default) option for authentication. If IS_ALL_ROUTES_PRIVATE is set to false,
|
|
25
27
|
* An array of private routes that are accessible to all authenticated users
|
|
26
28
|
* without specific role-based access control. Routes should be listed as string paths.
|
|
27
29
|
* Example: public static $privateRoutes = ['/']; // This makes the home page private
|
|
28
30
|
* Example: public static $privateRoutes = ['/profile', '/dashboard/settings']; // These routes are private
|
|
29
31
|
*/
|
|
30
|
-
public static $privateRoutes = [];
|
|
32
|
+
public static array $privateRoutes = [];
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* This is the (default) option for authentication. If IS_ALL_ROUTES_PRIVATE is set to true,
|
|
36
|
+
* An array of public routes that are accessible to all users, authenticated or not.
|
|
37
|
+
*/
|
|
38
|
+
public const DEFAULT_SIGNIN_REDIRECT = '/dashboard'; // Default redirect route after sign in
|
|
39
|
+
public const API_AUTH_PREFIX = '/api/auth'; // Prefix for third-party API authentication routes (github, google, etc.)
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* An array of public routes that are accessible to all users, authenticated or not.
|
|
43
|
+
* Routes should be listed as string paths.
|
|
44
|
+
* Example: public static $publicRoutes = ['/']; // This makes the home page public
|
|
45
|
+
* Example: public static $publicRoutes = ['/about', '/contact']; // These routes are public
|
|
46
|
+
*/
|
|
47
|
+
public static array $publicRoutes = ['/'];
|
|
48
|
+
public static array $authRoutes = [
|
|
49
|
+
'/signin',
|
|
50
|
+
'/signup',
|
|
51
|
+
];
|
|
31
52
|
|
|
32
53
|
/**
|
|
33
54
|
* An associative array mapping specific routes to required user roles for access control.
|
|
@@ -41,17 +62,21 @@ final class AuthConfig
|
|
|
41
62
|
* 'sales' => [self::ROLE_IDENTIFIER => [AuthRole::Admin, AuthRole::User]]
|
|
42
63
|
* ];
|
|
43
64
|
*/
|
|
44
|
-
public static $roleBasedRoutes = [];
|
|
65
|
+
public static array $roleBasedRoutes = [];
|
|
45
66
|
|
|
46
67
|
/**
|
|
47
68
|
* Checks if the given user role is authorized to access a set of roles.
|
|
48
69
|
*
|
|
49
|
-
* @param string $userRole The
|
|
50
|
-
* @param array $roles An array of AuthRole instances specifying allowed roles.
|
|
51
|
-
* @return bool Returns true if the user role
|
|
70
|
+
* @param \ArrayObject|string $userRole The user's role to check.
|
|
71
|
+
* @param array<AuthRole> $roles An array of AuthRole instances specifying allowed roles.
|
|
72
|
+
* @return bool Returns true if the user's role matches any of the allowed roles, false otherwise.
|
|
52
73
|
*/
|
|
53
|
-
public static function checkAuthRole($userRole, $roles)
|
|
74
|
+
public static function checkAuthRole(\ArrayObject|string $userRole, array $roles): bool
|
|
54
75
|
{
|
|
76
|
+
if ($userRole instanceof \ArrayObject) {
|
|
77
|
+
$userRole = $userRole[Auth::ROLE_NAME] ?? '';
|
|
78
|
+
}
|
|
79
|
+
|
|
55
80
|
foreach ($roles as $role) {
|
|
56
81
|
if ($userRole === $role->value) {
|
|
57
82
|
return true;
|
|
@@ -12,26 +12,62 @@ final class AuthMiddleware
|
|
|
12
12
|
{
|
|
13
13
|
public static function handle($requestPathname)
|
|
14
14
|
{
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
if (AuthConfig::IS_ALL_ROUTES_PRIVATE) {
|
|
16
|
+
$isLogin = Auth::getInstance()->isAuthenticated();
|
|
17
|
+
$isApiAuthRoute = stripos($requestPathname, AuthConfig::API_AUTH_PREFIX) === 0;
|
|
18
|
+
$isPublicRoute = self::matches($requestPathname, AuthConfig::$publicRoutes);
|
|
19
|
+
$isAuthRoute = self::matches($requestPathname, AuthConfig::$authRoutes);
|
|
20
|
+
|
|
21
|
+
// Skip the middleware if the route is api auth route
|
|
22
|
+
if ($isApiAuthRoute) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Redirect to the default sign in route if the user is already authenticated
|
|
27
|
+
if ($isAuthRoute) {
|
|
28
|
+
if ($isLogin) {
|
|
29
|
+
Request::redirect(AuthConfig::DEFAULT_SIGNIN_REDIRECT);
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Redirect to the default home route if the user is already authenticated
|
|
35
|
+
if (!$isLogin && !$isPublicRoute) {
|
|
36
|
+
Request::redirect("/signin");
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
// Skip the middleware if the route is public
|
|
40
|
+
if (!self::matches($requestPathname, AuthConfig::$privateRoutes)) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
19
43
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
44
|
+
// Check if the user is authorized to access the route or redirect to login
|
|
45
|
+
if (!self::isAuthorized()) {
|
|
46
|
+
Request::redirect('/signin');
|
|
47
|
+
}
|
|
23
48
|
}
|
|
24
49
|
|
|
25
50
|
// Check if the user has the required role to access the route or redirect to denied
|
|
26
|
-
if (AuthConfig::IS_ROLE_BASE
|
|
27
|
-
|
|
51
|
+
if (AuthConfig::IS_ROLE_BASE) {
|
|
52
|
+
$matchValue = self::hasRequiredRole($requestPathname);
|
|
53
|
+
if ($matchValue === "Route not in array") {
|
|
54
|
+
// echo "No validation needed for this route.";
|
|
55
|
+
} elseif ($matchValue === "Match") {
|
|
56
|
+
// echo "You are authorized to access this route";
|
|
57
|
+
} elseif ($matchValue === "Role mismatch") {
|
|
58
|
+
// echo "You are not authorized to access this route";
|
|
59
|
+
Request::redirect('/denied');
|
|
60
|
+
} else {
|
|
61
|
+
// echo "Unexpected error encountered";
|
|
62
|
+
}
|
|
28
63
|
}
|
|
29
64
|
}
|
|
30
65
|
|
|
31
|
-
protected static function matches($requestPathname)
|
|
66
|
+
protected static function matches(string $requestPathname, array $routes): bool
|
|
32
67
|
{
|
|
33
|
-
foreach (
|
|
34
|
-
|
|
68
|
+
foreach ($routes ?? [] as $pattern) {
|
|
69
|
+
$getUriRegexValue = self::getUriRegex($pattern, $requestPathname);
|
|
70
|
+
if ($getUriRegexValue) {
|
|
35
71
|
return true;
|
|
36
72
|
}
|
|
37
73
|
}
|
|
@@ -67,34 +103,44 @@ final class AuthMiddleware
|
|
|
67
103
|
return false;
|
|
68
104
|
}
|
|
69
105
|
|
|
70
|
-
protected static function hasRequiredRole($requestPathname):
|
|
106
|
+
protected static function hasRequiredRole(string $requestPathname): string
|
|
71
107
|
{
|
|
72
108
|
$auth = Auth::getInstance();
|
|
73
109
|
$roleBasedRoutes = AuthConfig::$roleBasedRoutes ?? [];
|
|
110
|
+
|
|
111
|
+
// Normalize the request path for matching
|
|
112
|
+
$requestPathnameValue = trim($requestPathname, '/');
|
|
113
|
+
|
|
74
114
|
foreach ($roleBasedRoutes as $pattern => $data) {
|
|
75
|
-
|
|
115
|
+
$patternValue = trim($pattern, '/');
|
|
116
|
+
if ($patternValue === $requestPathnameValue) {
|
|
117
|
+
// Route is found in array, check permissions
|
|
76
118
|
$userRole = Auth::ROLE_NAME ? $auth->getPayload()[Auth::ROLE_NAME] : $auth->getPayload();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
119
|
+
return ($userRole !== null && AuthConfig::checkAuthRole($userRole, $data[AuthConfig::ROLE_IDENTIFIER]))
|
|
120
|
+
? "Match"
|
|
121
|
+
: "Role mismatch";
|
|
80
122
|
}
|
|
81
123
|
}
|
|
82
|
-
|
|
124
|
+
|
|
125
|
+
// Route not found in role-based routes array
|
|
126
|
+
return "Route not in array";
|
|
83
127
|
}
|
|
84
128
|
|
|
85
|
-
private static function getUriRegex($pattern, $requestPathname)
|
|
129
|
+
private static function getUriRegex(string $pattern, string $requestPathname): int|bool
|
|
86
130
|
{
|
|
87
|
-
|
|
88
|
-
$
|
|
131
|
+
// Normalize both the pattern and the request path
|
|
132
|
+
$pattern = strtolower(trim($pattern, '/'));
|
|
133
|
+
$requestPathname = strtolower(trim($requestPathname, '/'));
|
|
89
134
|
|
|
90
135
|
// Handle the case where the requestPathname is empty, which means home or "/"
|
|
91
|
-
if (empty($requestPathname)
|
|
136
|
+
if (empty($requestPathname)) {
|
|
92
137
|
$requestPathname = '/';
|
|
93
138
|
} else {
|
|
94
|
-
$requestPathname = "
|
|
139
|
+
$requestPathname = "/$requestPathname";
|
|
95
140
|
}
|
|
96
141
|
|
|
97
|
-
|
|
142
|
+
// Construct the regex pattern
|
|
143
|
+
$regex = "#^/?" . preg_quote("/$pattern", '#') . "(/.*)?$#";
|
|
98
144
|
return preg_match($regex, $requestPathname);
|
|
99
145
|
}
|
|
100
146
|
}
|