PluginProbe
Yatra – Travel Booking & Tour Operator Software / trunk
Yatra – Travel Booking & Tour Operator Software vtrunk
3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 2.0.10 2.0.11 All 82 releases
yatra / app / Core / Handlers / LoginPageHandler.php

LoginPageHandler.php in Yatra – Travel Booking & Tour Operator Software trunk, at app/Core/Handlers/LoginPageHandler.php

170 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Yatra\Core\Handlers;
6
7 /**
8 * Login Page Handler
9 *
10 * Production-optimized handler for login page routing and template loading
11 *
12 * @package Yatra
13 * @version 1.0.0
14 */
15 class LoginPageHandler extends BasePageHandler
16 {
17 /**
18 * Handle the login page request with enhanced security
19 */
20 public function handle(array $params): bool
21 {
22 // Security: Validate request method
23 if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
24 $this->sendErrorResponse(405, __('Method not allowed', 'yatra'));
25 return false;
26 }
27
28 // Security: Rate limiting for login page access
29 if (!$this->checkRateLimit()) {
30 $this->sendErrorResponse(429, __('Too many requests', 'yatra'));
31 return false;
32 }
33
34 // Security: Check if user is already logged in and redirect securely
35 if (is_user_logged_in()) {
36 $current_user = wp_get_current_user();
37 $redirect_url = apply_filters('yatra_login_redirect_url', home_url('/' . \Yatra\Services\SettingsService::getAccountBase()), $current_user);
38
39 // Use safe redirect to prevent open redirects
40 wp_safe_redirect($redirect_url, 302);
41 exit;
42 }
43
44 // Security: Validate nonce if present (for form submissions)
45 if (isset($_GET['_wpnonce']) && !wp_verify_nonce($_GET['_wpnonce'], 'yatra_login_page')) {
46 $this->sendErrorResponse(403, __('Security check failed', 'yatra'));
47 return false;
48 }
49
50 // Configure $wp_query + virtual WP_Post (covers FSE block-theme rendering).
51 $this->setupPageEnvironment('singular', [
52 'title' => __('Login', 'yatra'),
53 'post_type' => 'page',
54 'post_name' => 'login',
55 ]);
56
57 // Security headers
58 $this->setSecurityHeaders();
59
60 if (!$this->selectTemplate('login-page', null, 'login')) {
61 // Fallback to shortcode if template is missing
62 return $this->handleFallback();
63 }
64
65 return true;
66 }
67
68 /**
69 * Get the route pattern for this handler
70 */
71 public function getPattern(): string
72 {
73 return '^login/?$';
74 }
75
76 /**
77 * Get the route name for this handler
78 */
79 public function getName(): string
80 {
81 return 'login';
82 }
83
84 /**
85 * Check rate limiting for login page access
86 */
87 private function checkRateLimit(): bool
88 {
89 $ip = $this->getClientIp();
90 $transient_key = 'yatra_login_page_limit_' . md5($ip);
91 $attempts = get_transient($transient_key) ?: 0;
92
93 // Allow 30 requests per 5 minutes
94 if ($attempts >= 30) {
95 return false;
96 }
97
98 set_transient($transient_key, $attempts + 1, 5 * MINUTE_IN_SECONDS);
99 return true;
100 }
101
102 /**
103 * Set security headers
104 */
105 private function setSecurityHeaders(): void
106 {
107 if (!headers_sent()) {
108 header('X-Content-Type-Options: nosniff');
109 header('X-Frame-Options: SAMEORIGIN');
110 header('Referrer-Policy: strict-origin-when-cross-origin');
111 header('Content-Security-Policy: "default-src \'self\'; script-src \'self\' \'unsafe-inline\'; style-src \'self\' \'unsafe-inline\'; img-src \'self\' data: https:; font-src \'self\' data:; connect-src \'self\'"');
112 }
113 }
114
115 /**
116 * Handle fallback when template is not available
117 */
118 private function handleFallback(): bool
119 {
120 // Fallback to shortcode rendering
121 add_filter('template_include', function($template) {
122 return get_template_directory() . '/page.php';
123 });
124
125 // Create a virtual page
126 add_filter('the_content', function($content) {
127 return do_shortcode('[yatra_login]');
128 });
129
130 return true;
131 }
132
133 /**
134 * Send error response
135 */
136 private function sendErrorResponse(int $code, string $message): void
137 {
138 if (!headers_sent()) {
139 status_header($code);
140 header('Content-Type: text/html; charset=' . get_bloginfo('charset'));
141 }
142
143 wp_die(
144 esc_html($message),
145 esc_html__('Error', 'yatra'),
146 ['response' => $code]
147 );
148 }
149
150 /**
151 * Get client IP address
152 */
153 private function getClientIp(): string
154 {
155 $ip_keys = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'];
156
157 foreach ($ip_keys as $key) {
158 if (!empty($_SERVER[$key])) {
159 $ips = explode(',', $_SERVER[$key]);
160 $ip = trim($ips[0]);
161 if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
162 return $ip;
163 }
164 }
165 }
166
167 return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
168 }
169 }
170