diff --git a/README.md b/README.md
index 9b32b79..45d4e11 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,9 @@ Authenticate WordPress user via json web token from Laravel Application.
- Login via JWT token
- Admin settings page
- Custom invalid token page
+- Optional debug mode with full exception details and stack traces
+
+Debug mode is disabled by default. An administrator can enable it from **Settings > Mahak Authentication** while troubleshooting. Because diagnostic pages expose server paths and other technical details to visitors of the login URL, disable it again after diagnosing the problem.
## Usage
@@ -32,4 +35,4 @@ Payload JWT:
"username" : "test-user"
}
}
-```
\ No newline at end of file
+```
diff --git a/dabestaniha-authenticate-bridge.php b/dabestaniha-authenticate-bridge.php
index 59a071e..9067735 100644
--- a/dabestaniha-authenticate-bridge.php
+++ b/dabestaniha-authenticate-bridge.php
@@ -3,7 +3,7 @@
/**
* Plugin Name: Mahak Authenticate Bridge
* Description: Authenticate WordPress user via json web token from Mahakiha Application.
- * Version: 2.0
+ * Version: 2.1.0
* Requires PHP: 7.4
* Author: Dabestaniha
*
diff --git a/src/app/Http/Controllers/AuthenticateController.php b/src/app/Http/Controllers/AuthenticateController.php
index dfb5356..c53d558 100644
--- a/src/app/Http/Controllers/AuthenticateController.php
+++ b/src/app/Http/Controllers/AuthenticateController.php
@@ -4,6 +4,8 @@ namespace Dabestaniha\AuthenticateBridge\App\Http\Controllers;
use Dabestaniha\AuthenticateBridge\App\Http\Requests\MahakAuthenticateRequest;
use Dabestaniha\AuthenticateBridge\App\Support\JwtDecoder;
+use RuntimeException;
+use Throwable;
use UnexpectedValueException;
class AuthenticateController extends InvocableController
@@ -31,18 +33,14 @@ class AuthenticateController extends InvocableController
{
$jwt_secret = get_configured_option('jwt-secret');
- try {
- $decoded = JwtDecoder::decodeHs256($token, $jwt_secret);
- $data = $decoded['data'] ?? null;
+ $decoded = JwtDecoder::decodeHs256($token, $jwt_secret);
+ $data = $decoded['data'] ?? null;
- if (!is_array($data)) {
- throw new UnexpectedValueException('JWT data must be an object.');
- }
-
- return $data;
- } catch (\Throwable $e) {
- wp_die(view('invalid-token'), 'Invalid Token', ['response' => 500]);
+ if (!is_array($data)) {
+ throw new UnexpectedValueException('JWT data must be an object.');
}
+
+ return $data;
}
public function find_or_create_user(string $identifier_name, string $identifier_value, string $name): int
@@ -63,17 +61,33 @@ class AuthenticateController extends InvocableController
$user_id = wp_create_user($username, $random_password, $email);
if (is_wp_error($user_id)) {
- wp_die(view('invalid-token'), 'Invalid Token', ['response' => 500]);
+ throw new RuntimeException(
+ 'WordPress could not create the user: '.$user_id->get_error_message()
+ );
}
- wp_update_user([
+ $updated_user_id = wp_update_user([
'ID' => $user_id,
'display_name' => $name,
]);
+ if (is_wp_error($updated_user_id)) {
+ throw new RuntimeException(
+ 'WordPress could not update the user: '.$updated_user_id->get_error_message()
+ );
+ }
+
return $user_id;
}
+ protected function handleException(Throwable $exception): void
+ {
+ $status = $exception->getCode() === 403 ? 403 : 500;
+ $fallbackView = $exception instanceof UnexpectedValueException ? 'invalid-token' : 'server-error';
+
+ mahak_render_error($exception, $status, $fallbackView);
+ }
+
public function login_user(int $user_id): bool
{
diff --git a/src/app/Http/Controllers/InvocableController.php b/src/app/Http/Controllers/InvocableController.php
index 745c53a..05866d3 100644
--- a/src/app/Http/Controllers/InvocableController.php
+++ b/src/app/Http/Controllers/InvocableController.php
@@ -4,30 +4,41 @@ namespace Dabestaniha\AuthenticateBridge\App\Http\Controllers;
use Dabestaniha\AuthenticateBridge\App\Http\Requests\BaseFormRequest;
use ReflectionMethod;
+use Throwable;
abstract class InvocableController
{
public static function resolve(): void
{
- $reflection = new ReflectionMethod(static::class, '__invoke');
-
- $args = [];
- foreach ($reflection->getParameters() as $param) {
- $class = $param->getType()->getName();
-
- if (is_subclass_of($class, BaseFormRequest::class)) {
- $request = new $class();
-
- if (!$request->isRequestForThisRoute()) {
- return;
- }
-
- $request->validate();
- $args[] = $request;
- }
- }
-
$controller = new static();
- $controller(...$args);
+
+ try {
+ $reflection = new ReflectionMethod(static::class, '__invoke');
+
+ $args = [];
+ foreach ($reflection->getParameters() as $param) {
+ $class = $param->getType()->getName();
+
+ if (is_subclass_of($class, BaseFormRequest::class)) {
+ $request = new $class();
+
+ if (!$request->isRequestForThisRoute()) {
+ return;
+ }
+
+ $request->validate();
+ $args[] = $request;
+ }
+ }
+
+ $controller(...$args);
+ } catch (Throwable $exception) {
+ $controller->handleException($exception);
+ }
}
-}
\ No newline at end of file
+
+ protected function handleException(Throwable $exception): void
+ {
+ throw $exception;
+ }
+}
diff --git a/src/app/Http/Controllers/SettingsPageFormController.php b/src/app/Http/Controllers/SettingsPageFormController.php
index f35d403..c784a0c 100644
--- a/src/app/Http/Controllers/SettingsPageFormController.php
+++ b/src/app/Http/Controllers/SettingsPageFormController.php
@@ -7,7 +7,16 @@ class SettingsPageFormController extends InvocableController
public function __invoke()
{
foreach (config('mahak.options') as $configured => $options_key) {
- register_setting(config('mahak.settings-group'), $options_key);
+ $args = [];
+
+ if ($configured === 'debug-mode') {
+ $args['sanitize_callback'] = function ($value): int {
+ return (int) filter_var($value, FILTER_VALIDATE_BOOLEAN);
+ };
+ $args['default'] = 0;
+ }
+
+ register_setting(config('mahak.settings-group'), $options_key, $args);
}
add_settings_section(
@@ -49,6 +58,14 @@ class SettingsPageFormController extends InvocableController
config('mahak.section-id')
);
+ add_settings_field(
+ config('mahak.options.debug-mode'),
+ config('mahak.translations.debug-mode'),
+ fn () => $this->debug_mode(),
+ config('mahak.settings-page'),
+ config('mahak.section-id')
+ );
+
$loginRouteOptionName = config('mahak.options.login-route');
add_filter("pre_update_option_{$loginRouteOptionName}", function ($value) {
return trim($value, '/');
@@ -103,4 +120,14 @@ class SettingsPageFormController extends InvocableController
echo "";
echo '';
}
-}
\ No newline at end of file
+
+ public function debug_mode(): void
+ {
+ $name = config('mahak.options.debug-mode');
+ $enabled = (bool) get_option($name, false);
+
+ echo "";
+ echo "';
+ }
+}
diff --git a/src/app/Http/Requests/BaseFormRequest.php b/src/app/Http/Requests/BaseFormRequest.php
index 7a075a9..236c370 100644
--- a/src/app/Http/Requests/BaseFormRequest.php
+++ b/src/app/Http/Requests/BaseFormRequest.php
@@ -3,6 +3,7 @@
namespace Dabestaniha\AuthenticateBridge\App\Http\Requests;
use Dabestaniha\AuthenticateBridge\App\Support\Collection;
+use UnexpectedValueException;
abstract class BaseFormRequest
{
@@ -44,7 +45,10 @@ abstract class BaseFormRequest
foreach ($rules as $rule) {
if (!$this->validateValue($value, $rule)) {
- wp_die(view('invalid-token'), 'Invalid Token', ['response' => 403]);
+ throw new UnexpectedValueException(
+ sprintf('The request field "%s" failed the "%s" validation rule.', $attribute, $rule),
+ 403
+ );
}
$data[$attribute] = $value;
diff --git a/src/configs/mahak.php b/src/configs/mahak.php
index a715794..900b20b 100644
--- a/src/configs/mahak.php
+++ b/src/configs/mahak.php
@@ -11,6 +11,7 @@ return [
'user-identifier' => 'mahak_user_identifier',
'login-route' => 'mahak_login_route',
'after-login-route' => 'mahak_after_login_route',
+ 'debug-mode' => 'mahak_debug_mode',
],
'user-identifiers' => [
@@ -37,7 +38,9 @@ return [
'user-identifier' => 'فیلد شناسایی کاربر',
'login-route' => 'مسیر لاگین ماهک',
'after-login-route' => 'مسیر بعد از لاگین',
+ 'debug-mode' => 'حالت اشکالزدایی',
+ 'debug-mode-description' => 'در صورت بروز خطا، جزئیات کامل فنی در صفحه نمایش داده شود. این گزینه را فقط هنگام عیبیابی فعال کنید.',
'new-user' => 'کاربر جدید',
],
-];
\ No newline at end of file
+];
diff --git a/src/helpers.php b/src/helpers.php
index 0c318fc..d08b01c 100644
--- a/src/helpers.php
+++ b/src/helpers.php
@@ -1,9 +1,10 @@
$exception]),
+ 'Mahak Authentication Error',
+ ['response' => $status]
+ );
+ }
+
+ wp_die(view($fallbackView), 'Authentication Error', ['response' => $status]);
+ }
+}
+
if (!function_exists('dd')) {
function dd(): void
{
diff --git a/src/resources/views/debug-error.php b/src/resources/views/debug-error.php
new file mode 100644
index 0000000..36d5275
--- /dev/null
+++ b/src/resources/views/debug-error.php
@@ -0,0 +1,31 @@
+
+
+
+
+
+ Mahak Authentication Error
+
+
+
+
+ Mahak Authentication Error
+
+ - Exception
+ - = esc_html(get_class($exception)) ?>
+ - Message
+ - = esc_html($exception->getMessage()) ?>
+ - Location
+ - = esc_html($exception->getFile().':'.$exception->getLine()) ?>
+
+ Stack trace
+ = esc_html($exception->getTraceAsString()) ?>
+
+
+
diff --git a/src/resources/views/server-error.php b/src/resources/views/server-error.php
index 31ce4f6..50deb0b 100644
--- a/src/resources/views/server-error.php
+++ b/src/resources/views/server-error.php
@@ -1,5 +1,5 @@
-
+
@@ -11,4 +11,4 @@
مشکلی پیش آمده، لطفا تا دقایق دیگر دوباره امتحان کنید.
بازگشت به صفحه اصلی
-
\ No newline at end of file
+