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.
@@ -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 = ltrim($pathname, '/');
49
+ $pathname = trim($pathname, '/');
50
50
  $baseDir = APP_PATH;
51
51
  $includePath = '';
52
52
  $layoutsToInclude = [];
@@ -181,7 +181,7 @@ class Auth
181
181
 
182
182
  $token = JWT::decode($jwt, new Key($this->secretKey, 'HS256'));
183
183
 
184
- if (empty($token->role)) {
184
+ if (empty($token->{Auth::PAYLOAD_NAME})) {
185
185
  return null;
186
186
  }
187
187
 
@@ -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 role of the user attempting to access the route.
50
- * @param array $roles An array of AuthRole instances specifying allowed roles.
51
- * @return bool Returns true if the user role is in the allowed roles, false otherwise.
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
- $requestPathname = trim($requestPathname);
16
- if (!self::matches($requestPathname)) {
17
- return;
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
- // Check if the user is authorized to access the route or redirect to login
21
- if (!self::isAuthorized()) {
22
- Request::redirect('/auth/login');
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 && !self::hasRequiredRole($requestPathname)) {
27
- Request::redirect('/denied');
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 (AuthConfig::$privateRoutes ?? [] as $pattern) {
34
- if (self::getUriRegex($pattern, $requestPathname)) {
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): bool
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
- if (self::getUriRegex($pattern, $requestPathname)) {
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
- if ($userRole !== null && AuthConfig::checkAuthRole($userRole, $data[AuthConfig::ROLE_IDENTIFIER])) {
78
- return true;
79
- }
119
+ return ($userRole !== null && AuthConfig::checkAuthRole($userRole, $data[AuthConfig::ROLE_IDENTIFIER]))
120
+ ? "Match"
121
+ : "Role mismatch";
80
122
  }
81
123
  }
82
- return false;
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
- $pattern = strtolower($pattern);
88
- $requestPathname = strtolower(trim($requestPathname));
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) || $requestPathname === '/') {
136
+ if (empty($requestPathname)) {
92
137
  $requestPathname = '/';
93
138
  } else {
94
- $requestPathname = "/" . $requestPathname;
139
+ $requestPathname = "/$requestPathname";
95
140
  }
96
141
 
97
- $regex = "#^/?" . preg_quote($pattern, '#') . "(/.*)?$#";
142
+ // Construct the regex pattern
143
+ $regex = "#^/?" . preg_quote("/$pattern", '#') . "(/.*)?$#";
98
144
  return preg_match($regex, $requestPathname);
99
145
  }
100
146
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-prisma-php-app",
3
- "version": "1.26.5",
3
+ "version": "1.26.7",
4
4
  "description": "Prisma-PHP: A Revolutionary Library Bridging PHP with Prisma ORM",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",