1 <?php
2 /**
3 * Application level Controller
4 *
5 * This file is application-wide controller file. You can put all
6 * application-wide controller-related methods here.
7 *
8 * PHP 5
9 *
10 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
11 * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
12 *
13 * Licensed under the Creative Commons BY-NC-SA 3.0 License
14 * Redistributions of files must retain the above copyright notice.
15 *
16 * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
17 * @link http://cakephp.org CakePHP(tm) Project
18 * @package app.Controller
19 * @since CakePHP(tm) v 0.2.9
20 * @license Creative Commons BY-NC-SA 3.0 License (http://creativecommons.org/licenses/by-nc-sa/3.0/)
21 *
22 * Here is the Doxygen Mainpage Content:
23 *
24 * \mainpage
25 *
26 * \section intro_sec Introduction
27 *
28 * Here is the developer documentation of the Models, Controllers and Views of the XLRstats webfront v3.
29 * This docs also cover the dashboard plugin that is part of the core app.
30 *
31 * \section installation_sec Installation
32 *
33 * Installation instructions can be found at www.xlrstats.com
34 *
35 */
36
37 App::uses('Controller', 'Controller');
38
39 /**
40 * Application Controller
41 *
42 * Add your application-wide methods in the class below, your controllers
43 * will inherit them.
44 *
45 * @package app.Controller
46 * @link http://book.cakephp.org/2.0/en/controllers.html#the-app-controller
47 */
48 class AppController extends Controller {
49
50 /**
51 * Models
52 *
53 * @var array
54 */
55 public $uses = array(
56 'Dashboard.Option',
57 'Dashboard.Server',
58 'Dashboard.ServerOption',
59 'Dashboard.AppUser',
60 );
61
62 /**
63 * Helpers
64 *
65 * @var array
66 */
67 public $helpers = array(
68 'XlrFunctions',
69 'TwitterBootstrap.TwitterBootstrap',
70 'Gravatar.Gravatar'
71 );
72
73 /**
74 * Components
75 *
76 * @var array
77 */
78 public $components = array(
79 'XlrFunctions',
80 'DebugKit.Toolbar' => array(
81 'panels' => array('ClearCache.ClearCache')
82 ),
83 'Users.RememberMe',
84 'Session',
85 'Cookie',
86 'Acl',
87 'Auth'
88 );
89
90 /**
91 * An array of user data
92 *
93 * @var array
94 */
95 public $user = array();
96
97 //-------------------------------------------------------------------
98
99 /**
100 * Called before the controller action.
101 */
102 public function beforeFilter() {
103 /* LOAD ORDER IS IMPORTANT!!! */
104 /* Are we in a subdomain? */
105 $this->getSubdomain();
106 /* Load default options */
107 $this->loadConfigOptions();
108 /* Fetch user information */
109 $this->getUserData();
110 /* Before we do anything else, get the available servers and the database id to determine which server we are dealing with */
111 $this->loadB3Servers();
112 $this->getDatabaseId();
113 /* Now we have a server id we load the rest */
114 $this->loadServerConfigOptions();
115 $this->loadGameConfig();
116 $this->getServerGroupId();
117 $this->checkAuthorization();
118 $this->checkLicense();
119 /* We check authorization here to display dashboard link in login menu or not */
120 $this->isAuthorized();
121 /* Check if we need to disable/enable Caching for this controller. */
122 $this->checkCaching();
123
124 parent::beforeFilter();
125
126 if (Configure::read('debug') < 2) {
127 $this->Components->unload('DebugKit.Toolbar');
128 }
129
130 $this->theme = Configure::read('options.theme');
131 $this->RememberMe->restoreLoginFromCookie();
132
133 $this->Auth->loginAction = array('admin' => false, 'plugin' => 'dashboard', 'controller' => 'app_users', 'action' => 'login');
134 $this->Auth->authError = __('Did you really think you are allowed to see that?');
135 $this->Auth->unauthorizedRedirect = array('admin' => false, 'plugin' => null, 'controller' => 'pages', 'action' => 'display', 'server' => Configure::read('server_id'));
136 }
137
138 //-------------------------------------------------------------------
139
140 /**
141 * Called after the controller action is run, but before the view is rendered.
142 */
143 public function beforeRender() {
144 parent::beforeRender();
145 /* To make the $user array available in view files... */
146 $this->set('user', $this->user);
147 }
148
149 //-------------------------------------------------------------------
150
151 /**
152 * Checks caching for defined plugins and controllers
153 */
154 public function checkCaching() {
155 /* Plugins that shouldn't be cached */
156 $plugins = array();
157 /* Controllers that shouldn't be cached */
158 $controllers = array('player_stats');
159
160 if (in_array($this->request->plugin, $plugins) || in_array($this->request->controller, $controllers)) {
161 Configure::write('Cache.disable', true);
162 $this->response->disableCache();
163 $this->set('isCaching', false);
164 } else {
165 $this->set('isCaching', true);
166 }
167 }
168
169 //-------------------------------------------------------------------
170
171 /**
172 * Check if we are in a subdomain
173 * @return string url
174 * @return null
175 */
176 public function getSubdomain() {
177 $url = explode('.', $_SERVER['HTTP_HOST'], 3); //creates the various parts
178 if (count($url) <= 2 OR $url[0] === 'www') {
179 Configure::write('server.subdomain', 'www');
180 } else {
181 Configure::write('server.subdomain', $url[0]);
182 }
183 }
184
185 //-------------------------------------------------------------------
186
187 /**
188 * Determines which B3 database we need to access.
189 * See AppModel::__construct() for database selection logic.
190 *
191 * First check if we have a server parameter in our url, if so save it to config and session
192 * If we have multiple controllers after our initial call, we need our session data to use the proper DB
193 * Last, if no server is known, and no session data is available, fall back to our first available server
194 */
195 public function getDatabaseId() {
196 if (isset($this->request->server)) {
197 $this->Session->write('server_id', $this->request->server);
198 Configure::write('server_id', $this->request->server);
199 //debug('server parameter found! ' . $this->request->server);
200 } elseif ($this->Session->check('server_id')) {
201 Configure::write('server_id', $this->Session->read('server_id'));
202 } else {
203 Configure::write('server_id', Configure::read('first_server_id'));
204 //debug('server parameter NOT found!');
205 }
206 }
207
208 //-------------------------------------------------------------------
209
210 /**
211 * Loads Configuration options
212 */
213 public function loadConfigOptions() {
214 if (isset($this->Option) && !empty($this->Option->table) && !Configure::read('loaded.options')) {
215 $this->Option->load(); // Load global options
216 Configure::write('loaded.options', true); // Reduce Queries if options are already loaded
217 }
218 }
219
220 //-------------------------------------------------------------------
221
222 /**
223 * Loads Server specific Configuration options
224 */
225 public function loadServerConfigOptions() {
226 if (isset($this->ServerOption) && !empty($this->ServerOption->table) && !Configure::read('loaded.serveroptions')) {
227 $this->ServerOption->load(); // Override server specific options
228 Configure::write('loaded.serveroptions', true); // Reduce Queries if options are already loaded
229 }
230 }
231
232 //-------------------------------------------------------------------
233
234 /**
235 * Loads information for all B3 servers
236 */
237 public function loadB3Servers() {
238 if (isset($this->Server) && !empty($this->Server->table) && !Configure::read('loaded.servers')) {
239 $user = $this->user;
240 $request = $this->request;
241 $this->Server->getB3ServerData($user, $request);
242 // Reduce Queries if servers are already loaded
243 Configure::write('loaded.servers', true);
244 }
245 }
246
247 //-------------------------------------------------------------------
248
249 /**
250 * Loads game config file
251 */
252 public function loadGameConfig() {
253 $serverID = Configure::read('server_id');
254 $gameName = Configure::read('servers.' . $serverID . '.gamename');
255
256 try {
257 Configure::load('games' . DS . $gameName);
258 } catch (Exception $e) {
259 //debug('ERROR: ' . $e->getMessage());
260 /* This must be a server that does not exist, so clear the session and go 'home' */
261 $this->Session->delete('server_id');
262 $this->Cookie->delete('server_id');
263 $this->Session->setFlash(__('That was not a valid request...'), null, null, 'error');
264 $this->redirect('/');
265 }
266 }
267
268 //-------------------------------------------------------------------
269
270 /**
271 * Controls the Authorization using cakePHP's built-in ActionsAuthorize and ControllerAuthorize handlers.
272 *
273 * ActionsAuthorize Uses the AclComponent to check for permissions on an action level.
274 * ControllerAuthorize Calls isAuthorized() on the active controller, and uses the return of that to
275 * authorize a user.
276 *
277 * We use three basic built-in user groups in our database;
278 * - Super Admin : Has root access system wide.
279 * - Admin : Has administrative access to users and server options management within the server group
280 * he is assigned. An admin can be assigned to one or more server groups and belongs to
281 * serverGroupAdmins array configured in global configuration.
282 * - User : Has access only to public pages.
283 */
284 public function checkAuthorization() {
285 // First authorization check is handled by ActionsAuthorize
286 $this->Auth->authorize = array(
287 'Actions' => array(
288 'actionPath' => 'controllers/',
289 'userModel' => 'AppUser',
290 )
291 );
292 // We allow access to all public (non-admin) pages
293 if ($this->params['prefix'] != 'admin') {
294 $this->Auth->allow();
295 } else {
296 $serverGroupAdmins = Configure::read('globals.advanced.serverGroupAdmins');
297 /*
298 * If the user is part of serverGroupAdmins, hand the authorization to ControllerAuthorize which calls
299 * isAuthorized() action to check authorization.
300 */
301 if (isset($this->user['Group']['name']) && in_array($this->user['Group']['name'], $serverGroupAdmins)) {
302 $this->Auth->authorize = array('Controller');
303 /*
304 * If the user is authorized, i.e. if the admin has access rights in the current server group,
305 * we check the access rights finally again using ActionsAuthorize to make sure that the user has a
306 * limited admin access as we set in acos_aros table.
307 */
308 if ($this->isAuthorized()) {
309 $this->Auth->authorize = array(
310 'Actions' => array(
311 'actionPath' => 'controllers/',
312 'userModel' => 'AppUser',
313 )
314 );
315 }
316 }
317 }
318 }
319
320 //-------------------------------------------------------------------
321
322 /**
323 * Sets $user variable that holds an array of user information
324 * to use in controllers and views.
325 */
326 public function getUserData() {
327 if ($this->Auth->loggedIn()) {
328 $this->user = $this->AppUser->getUserData($this->Auth->user('id'));
329 }
330 $this->set('user', $this->user);
331 }
332
333 //-------------------------------------------------------------------
334
335 /**
336 * Writes current server_group_id to a session var
337 */
338 public function getServerGroupId() {
339 $serverID = Configure::read('server_id');
340 $this->Session->write('server_group_id', Configure::read('servers.' . $serverID . '.server_group_id'));
341 return true;
342 }
343
344 //-------------------------------------------------------------------
345
346 /**
347 * Used to check if a serverGroupAdmin is authorized to access a certain server group
348 */
349 public function isAuthorized() {
350 $currentServerGroupId = $this->Session->read('server_group_id');
351 $userServerGroupIds = array();
352
353 if (isset($this->user['ServerGroup'])) {
354 foreach ($this->user['ServerGroup'] as $serverGroup) {
355 $userServerGroupIds[] = $serverGroup['id'];
356 }
357 }
358 //pr($userServerGroupIds);
359 if (isset($this->user['User']['group_id'])) {
360 $groupID = $this->user['User']['group_id'];
361 } else {
362 $groupID = null;
363 }
364
365 if (in_array($currentServerGroupId, $userServerGroupIds) || $groupID == 1) {
366 $this->set('isAuthorized', true);
367 return true;
368 }
369 $this->set('isAuthorized', false);
370 return false;
371 }
372
373 //-------------------------------------------------------------------
374
375 /**
376 * Checks license
377 */
378 public function checkLicense() {
379 $invCookie = $this->Cookie->read('license_invalid');
380 if (!$this->XlrFunctions->isLicenseValid() && !isset($invCookie)) {
381 $this->Session->setFlash(__('This is an unlicensed version. Please visit <a href="http://www.xlrstats.com/pages/xlrstats.com/licensing">the XLRstats licensing page</a> for more info.'), null, null, 'error');
382 $this->Cookie->write('license_invalid', 'shown', false, '1 day');
383 }
384 }
385
386 //-------------------------------------------------------------------
387
388 /**
389 * Returns server name
390 *
391 * @param null $serverID
392 * @return mixed
393 */
394 public function getServerName($serverID = null) {
395 if ($serverID == null) {
396 $serverID = Configure::read('server_id');
397 }
398 $serverName = $this->Server->serverName($serverID);
399
400 if ($this->request->is('requested')) {
401 return $serverName;
402 }
403 return $serverName;
404 }
405
406 }
407