create-prisma-php-app 1.20.519 → 1.20.520

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.
@@ -8,6 +8,7 @@ require_once __DIR__ . '/vendor/autoload.php';
8
8
  require_once __DIR__ . '/settings/paths.php';
9
9
 
10
10
  use Lib\Middleware\AuthMiddleware;
11
+ use Lib\Auth\Auth;
11
12
  use Dotenv\Dotenv;
12
13
 
13
14
  $dotenv = Dotenv::createImmutable(\DOCUMENT_PATH);
@@ -136,8 +137,9 @@ function getFilePrecedence()
136
137
 
137
138
  function uriExtractor(string $scriptUrl): string
138
139
  {
139
- $prismaPHPSettings = json_decode(file_get_contents("prisma-php.json"), true);
140
- $projectName = $prismaPHPSettings['projectName'] ?? '';
140
+ global $_prismaPHPSettings;
141
+
142
+ $projectName = $_prismaPHPSettings['projectName'] ?? '';
141
143
  if (empty($projectName)) {
142
144
  return "/";
143
145
  }
@@ -383,44 +385,6 @@ function setupErrorHandling(&$content)
383
385
  });
384
386
  }
385
387
 
386
- ob_start();
387
- require_once SETTINGS_PATH . '/public-functions.php';
388
- require_once SETTINGS_PATH . '/request-methods.php';
389
- $_metadataFile = APP_PATH . '/metadata.php';
390
- $_metadataArray = file_exists($_metadataFile) ? require_once $_metadataFile : [];
391
- $_filesListRoutes = [];
392
- /**
393
- * @var array $metadata Metadata information
394
- */
395
- $metadata = [];
396
- /**
397
- * @var string $uri The URI of the current request
398
- */
399
- $uri = "";
400
- /**
401
- * @var string $pathname The pathname of the current request
402
- */
403
- $pathname = "";
404
- /**
405
- * @var array $dynamicRouteParams The dynamic route parameters
406
- */
407
- $dynamicRouteParams = [];
408
- /**
409
- * @var string $content The content to be included in the main layout file
410
- */
411
- $content = "";
412
- /**
413
- * @var string $childContent The child content to be included in the layout file
414
- */
415
- $childContent = "";
416
- /**
417
- * @var array $mainLayoutHead The head content to be included in the main layout file
418
- */
419
- $mainLayoutHead = [];
420
- /**
421
- * @var array $mainLayoutFooter The footer content to be included in the main layout file
422
- */
423
- $mainLayoutFooter = [];
424
388
 
425
389
  function containsChildContent($filePath)
426
390
  {
@@ -615,6 +579,76 @@ function getLoadingsFiles()
615
579
  return '';
616
580
  }
617
581
 
582
+ function authenticateUserToken()
583
+ {
584
+ $token = getBearerToken();
585
+ if ($token) {
586
+ $auth = Auth::getInstance();
587
+ $verifyToken = $auth->verifyToken($token);
588
+ if ($verifyToken) {
589
+ $auth->authenticate($verifyToken);
590
+ }
591
+ }
592
+ }
593
+
594
+ function getPrismaSettings(): \ArrayObject
595
+ {
596
+ $_prismaPHPSettingsFile = DOCUMENT_PATH . '/prisma-php.json';
597
+
598
+ if (file_exists($_prismaPHPSettingsFile)) {
599
+ $jsonContent = file_get_contents($_prismaPHPSettingsFile);
600
+ $decodedJson = json_decode($jsonContent, true);
601
+
602
+ if (json_last_error() === JSON_ERROR_NONE) {
603
+ return new \ArrayObject($decodedJson, \ArrayObject::ARRAY_AS_PROPS);
604
+ } else {
605
+ return new \ArrayObject([]);
606
+ }
607
+ }
608
+ }
609
+
610
+ ob_start();
611
+ require_once SETTINGS_PATH . '/public-functions.php';
612
+ require_once SETTINGS_PATH . '/request-methods.php';
613
+ $_metadataFile = APP_PATH . '/metadata.php';
614
+ $_metadataArray = file_exists($_metadataFile) ? require_once $_metadataFile : [];
615
+ $_filesListRoutes = [];
616
+ $_prismaPHPSettings = getPrismaSettings();
617
+ $_fileToInclude = '';
618
+
619
+ /**
620
+ * @var array $metadata Metadata information
621
+ */
622
+ $metadata = [];
623
+ /**
624
+ * @var string $uri The URI of the current request
625
+ */
626
+ $uri = "";
627
+ /**
628
+ * @var string $pathname The pathname of the current request
629
+ */
630
+ $pathname = "";
631
+ /**
632
+ * @var array $dynamicRouteParams The dynamic route parameters
633
+ */
634
+ $dynamicRouteParams = [];
635
+ /**
636
+ * @var string $content The content to be included in the main layout file
637
+ */
638
+ $content = "";
639
+ /**
640
+ * @var string $childContent The child content to be included in the layout file
641
+ */
642
+ $childContent = "";
643
+ /**
644
+ * @var array $mainLayoutHead The head content to be included in the main layout file
645
+ */
646
+ $mainLayoutHead = [];
647
+ /**
648
+ * @var array $mainLayoutFooter The footer content to be included in the main layout file
649
+ */
650
+ $mainLayoutFooter = [];
651
+
618
652
  try {
619
653
  $_determineContentToInclude = determineContentToInclude();
620
654
  checkForDuplicateRoutes();
@@ -622,6 +656,7 @@ try {
622
656
  $_layoutsToInclude = $_determineContentToInclude['layouts'] ?? [];
623
657
  $uri = $_determineContentToInclude['uri'] ?? '';
624
658
  $pathname = $uri ? "/" . $uri : "/";
659
+ $_fileToInclude = basename($_contentToInclude);
625
660
 
626
661
  if (empty($_contentToInclude)) {
627
662
  if (!$isXFilRequest) {
package/dist/index.js CHANGED
@@ -343,18 +343,23 @@ function modifyLayoutPHP(baseDir, answer) {
343
343
  if (checkExcludeFiles(layoutPath)) return;
344
344
  try {
345
345
  let indexContent = fs.readFileSync(layoutPath, "utf8");
346
- const stylesAndLinks = `\n <link href="<?php echo $baseUrl; ?>/css/index.css" rel="stylesheet">\n <script src="<?php echo $baseUrl; ?>/js/index.js"></script>`;
346
+ let stylesAndLinks = "";
347
+ if (!answer.backendOnly) {
348
+ stylesAndLinks = `\n <link href="<?php echo $baseUrl; ?>/css/index.css" rel="stylesheet">\n <script src="<?php echo $baseUrl; ?>/js/index.js"></script>`;
349
+ }
347
350
  // Tailwind CSS link or CDN script
348
- const tailwindLink = answer.tailwindcss
349
- ? ` <link href="<?php echo $baseUrl; ?>/css/styles.css" rel="stylesheet"> ${stylesAndLinks}`
350
- : ` <script src="https://cdn.tailwindcss.com"></script> ${stylesAndLinks}`;
351
+ let tailwindLink = "";
352
+ if (!answer.backendOnly) {
353
+ tailwindLink = answer.tailwindcss
354
+ ? ` <link href="<?php echo $baseUrl; ?>/css/styles.css" rel="stylesheet"> ${stylesAndLinks}`
355
+ : ` <script src="https://cdn.tailwindcss.com"></script> ${stylesAndLinks}`;
356
+ }
351
357
  // Insert before the closing </head> tag
352
358
  indexContent = indexContent.replace(
353
359
  "</head>",
354
360
  `${tailwindLink}\n <!-- Dynamic Head -->
355
361
  <?php echo implode("\\n", $mainLayoutHead); ?></head>`
356
362
  );
357
- console.log("🚀 ~ modifyLayoutPHP ~ indexContent:", indexContent);
358
363
  fs.writeFileSync(layoutPath, indexContent, { flag: "w" });
359
364
  console.log(
360
365
  chalk.green(
@@ -88,3 +88,32 @@ function isXFilRequest(): bool
88
88
 
89
89
  return false;
90
90
  }
91
+
92
+ /**
93
+ * Get the Bearer token from the Authorization header.
94
+ *
95
+ * @return string|null The Bearer token or null if not present.
96
+ */
97
+ function getBearerToken(): ?string
98
+ {
99
+ // Normalize headers to handle case-insensitive keys
100
+ $headers = array_change_key_case(getallheaders(), CASE_LOWER);
101
+ $authHeader = $headers['authorization'] ?? null;
102
+
103
+ // If not found, try fetching it from $_SERVER as a fallback
104
+ if (!$authHeader && isset($_SERVER['HTTP_AUTHORIZATION'])) {
105
+ $authHeader = $_SERVER['HTTP_AUTHORIZATION'];
106
+ }
107
+
108
+ // Fallback for Apache servers
109
+ if (!$authHeader && isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
110
+ $authHeader = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
111
+ }
112
+
113
+ // Check if the Authorization header is in the expected Bearer format
114
+ if ($authHeader && preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
115
+ return $matches[1];
116
+ }
117
+
118
+ return null;
119
+ }
@@ -37,7 +37,6 @@ if (existsSync(bsConnectionInfo)) {
37
37
  console.warn("bs-output.json not found, using default connection info.");
38
38
  }
39
39
 
40
- // Swagger options
41
40
  const options = {
42
41
  definition: {
43
42
  openapi: "3.0.0",
@@ -49,11 +48,25 @@ const options = {
49
48
  servers: [
50
49
  {
51
50
  url: jsonData.local, // For Development
52
- description: "Server",
51
+ description: "Development Server",
53
52
  },
54
53
  {
55
- url: "your-domain", // For Production
56
- description: "Server",
54
+ url: "your-production-domain", // For Production
55
+ description: "Production Server",
56
+ },
57
+ ],
58
+ components: {
59
+ securitySchemes: {
60
+ bearerAuth: {
61
+ type: "http",
62
+ scheme: "bearer",
63
+ bearerFormat: "JWT",
64
+ },
65
+ },
66
+ },
67
+ security: [
68
+ {
69
+ bearerAuth: [],
57
70
  },
58
71
  ],
59
72
  },
@@ -100,13 +100,22 @@ class Auth
100
100
  */
101
101
  public function isAuthenticated(): bool
102
102
  {
103
+ global $_fileToInclude;
104
+
103
105
  if (!isset($_COOKIE[self::COOKIE_NAME])) {
104
106
  unset($_SESSION[self::PAYLOAD]);
105
107
  return false;
106
108
  }
107
109
 
108
- $jwt = $_COOKIE[self::COOKIE_NAME];
110
+ if ($_fileToInclude === 'route.php') {
111
+ $bearerToken = getBearerToken();
112
+ $verifyBearerToken = $this->verifyToken($bearerToken);
113
+ if (!$verifyBearerToken) {
114
+ return false;
115
+ }
116
+ }
109
117
 
118
+ $jwt = $_COOKIE[self::COOKIE_NAME];
110
119
  $verifyToken = $this->verifyToken($jwt);
111
120
  if ($verifyToken === false) {
112
121
  return false;
@@ -148,17 +157,31 @@ class Auth
148
157
 
149
158
  /**
150
159
  * Verifies the JWT token and returns the decoded payload if the token is valid.
151
- * If the token is invalid, an exception is thrown.
160
+ * If the token is invalid or expired, null is returned.
152
161
  *
153
162
  * @param string $jwt The JWT token to verify.
154
- * @return object Returns the decoded payload if the token is valid.
163
+ * @return object|null Returns the decoded payload if the token is valid, or null if invalid or expired.
155
164
  */
156
- public function verifyToken(string $jwt)
165
+ public function verifyToken(?string $jwt): ?object
157
166
  {
158
167
  try {
159
- return JWT::decode($jwt, new Key($this->secretKey, 'HS256'));
168
+ if (!$jwt) {
169
+ return null;
170
+ }
171
+
172
+ $token = JWT::decode($jwt, new Key($this->secretKey, 'HS256'));
173
+
174
+ if (empty($token->role)) {
175
+ return null;
176
+ }
177
+
178
+ if (isset($token->exp) && time() >= $token->exp) {
179
+ return null;
180
+ }
181
+
182
+ return $token;
160
183
  } catch (\Exception) {
161
- throw new \InvalidArgumentException("Invalid token.");
184
+ return null;
162
185
  }
163
186
  }
164
187
 
@@ -2,7 +2,8 @@
2
2
 
3
3
  $welcome = 'Welcome to the Prisma PHP Backend Only Starter Kit! This starter kit provides a powerful foundation for building robust PHP applications with Prisma PHP ORM, a modern database toolkit. To create a new route, follow these steps:
4
4
  1. Create a new folder inside the "src/app" directory with the name of your route.
5
- 2. Inside the newly created folder, create a route.php file to define your route logic.
5
+ 2. Inside the newly created folder, create a route.php file. src/app/your-route/route.php
6
+ 3. Define your route logic inside the route.php file.
6
7
 
7
8
  This will serve as your API endpoint for the newly created route. Feel free to customize and extend the functionality as needed. Happy coding!
8
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-prisma-php-app",
3
- "version": "1.20.519",
3
+ "version": "1.20.520",
4
4
  "description": "Prisma-PHP: A Revolutionary Library Bridging PHP with Prisma ORM",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",