View difference between Paste ID: Jfgv7NtQ and WvvkmcUZ
SHOW: | | - or go back to the newest paste.
1
<?php
2
3
/**
4
 * Wireframe
5
 * Most light-weight multi-host framework *ever*.
6
 * @author Sim
7
 * @php 5.7
8
 */
9
class FSO_Admin
10
{
11
	private $_dbh;
12
13
	const API_URL = "http://178.238.225.27:8080";
14
15
	public function __construct() 
16
	{
17
		session_start();
18
19
		if(isset($_SESSION['expires_at'])):
20
			if(time() >= $_SESSION['expires_at']):
21
				unset($_SESSION['expires_at']);
22
				unset($_SESSION['access_token']);
23
			endif;
24
		endif;
25
26
		$this->_dbh = new wf_modules\WireframeDatabase([
27
			'string'   => 'mysql:host=localhost;dbname=fso',
28
			'username' => 'root',
29
			'password' => '',
30
			'options'  => [
31
				PDO::ATTR_PERSISTENT => TRUE,
32
				PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
33
			]
34
		]);
35
	}
36
37
	/**
38
	 * _log(String $message)
39
	 * Log message to a file (logs.txt)
40
	 */
41
	private function _log($message)
42
	{
43
		file_put_contents(APP_PATH . '/logs.txt', '[' . date('d-m-Y h:i:s') . '] ' . $message .PHP_EOL, FILE_APPEND | LOCK_EX);
44
	}
45
46
	/**
47
	 * run(Wireframe\Router $router)
48
	 * Define all routing closures
49
	 */
50
	public function run(Wireframe\Router $router)
51
	{
52
		/**
53
		 * Index route
54
		 * Display a confusing "It works!"
55
		 */
56
		$router->get('/', function()
57
		{
58
			return 'It works!';
59
		}, CACHE_ROUTE);
60
61
		/**
62
		 * Hidden admin route
63
		 * Display admin_panel.phtml
64
		 */
65
		$router->get('/charvatia', function()
66
		{
67
			return (new wf_modules\WireframeTemplate())->render("admin_panel.phtml");
68
		}, CACHE_ROUTE);
69
70
		/**
71
		 * PHPAPI: login
72
		 * Get an access token from FreeSO's API
73
		 * Communicates with external API: Yes
74
		 */
75
		$router->post('/login', function($username = FALSE, $password = FALSE) 
76
		{
77
			header('Content-Type: application/json');
78
79
			if(!$username || !$password):
80
				return json_encode([
81
					'error_code'    => 'EMPTY_FIELDS',
82
					'error_message' => 'Please enter all fields.'
83
				]);
84
			endif;
85
86
			$result = $this->_doPost(
87
				self::API_URL . '/admin/oauth/token',
88
				array('Content-Type: application/x-www-form-urlencoded'),
89
				array(
90
					'grant_type' => 'password', 
91
					'username'   => $username, 
92
					'password'   => $password
93
				)
94
			);
95
96
			if ($result === FALSE): 
97
				return json_encode([
98
					'error_code'    => 'BAD_REQUEST',
99
					'error_message' => 'There was a problem with the request.'
100
				]);
101
			endif;
102
103
			$result = json_decode($result, TRUE);
104
105
			if(isset($result['access_token'])) {
106
				$_SESSION['access_token'] = $result['access_token'];
107
				$_SESSION['expires_at'] = time() + $result['expires_in'];
108
			} else {
109
				return json_encode([
110
					'error_code'    => 'RESPONSE_ERROR',
111
					'error_message' => 'Invalid credentials.'
112
				]);
113
			}
114
115
			$this->_log($_SERVER['REMOTE_ADDR'] . ' logged in');
116
			return json_encode(['success' => TRUE]);
117
		});
118
119
		/**
120
		 * PHPAPI: register
121
		 * Queries the FreeSO API to create a user
122
		 * Communicates with external API: Yes
123
		 */
124
		$router->post('/register', function($username = FALSE, $email = FALSE, $password = FALSE) 
125
		{
126
			header('Content-Type: application/json');
127
128
			if(!isset($_SESSION['access_token'])):
129
				return json_encode([
130
					'error_code' => 'NO_AUTH',
131
					'error_message' => 'You have to login first.'
132
				]);
133
			endif;
134
135
			if(!$username || !$email || !$password):
136
				return json_encode([
137
					'error_code'    => 'EMPTY_FIELDS',
138
					'error_message' => 'Please enter all fields.'
139
				]);
140
			endif;
141
142
			$result = $this->_doPost(
143
				self::API_URL . '/userapi/registration',
144
				array('Content-Type: application/x-www-form-urlencoded'),
145
				array( 
146
					'username'   => $username, 
147
					'email'      => $email,
148
					'password'   => $password
149
				)
150
			);
151
152
			if($result):
153
				$this->_log($_SERVER['REMOTE_ADDR'] . ' created an account: ' . $username);
154
				return json_encode(['success' => TRUE]);
155
			endif;
156
157
			return json_encode([
158
				'error_code' => 'BAD_REQUEST',
159
				'error_message' => 'There was a problem with the request.'
160
			]);
161
		});
162
163
		/**
164
		 * PHPAPI: announce
165
		 * Queries the FreeSO API to make a broadcast
166
		 * Communicates with external API: Yes
167
		 */
168-
		$router->post('/announce', function($subject = false, $message = false)
168+
		$router->post('/shards/announce', function($subject = false, $message = false)
169
		{
170
			header('Content-Type: application/json');
171
172
			if(!isset($_SESSION['access_token'])):
173
				return json_encode([
174
					'error_code' => 'NO_AUTH',
175
					'error_message' => 'You have to login first.'
176
				]);
177
			endif;
178
179
			if(!$subject || !$message):
180
				return json_encode([
181
					'error_code'    => 'EMPTY_FIELDS',
182
					'error_message' => 'Please enter all fields.'
183
				]);
184
			endif;
185
186
			$result = $this->_doPost(
187
				self::API_URL . '/admin/shards/announce',
188
				array(
189
					'Content-Type: application/x-www-form-urlencoded',
190
					'Authorization: bearer ' . $_SESSION['access_token'] 
191
				),
192
				array(
193
					'sender' => $this->_getRandomName(), 
194
					'subject' => $subject, 
195
					'message' => $message
196
				)
197
			);	
198
199
			if($result):
200
				$this->_log($_SERVER['REMOTE_ADDR'] . ' announced: ' . $message);
201
				return json_encode(['success' => TRUE]);
202
			endif;
203
204
			return json_encode([
205
				'error_code' => 'BAD_REQUEST',
206
				'error_message' => 'There was a problem with the request.'
207
			]);
208
		});
209
210
		/**
211
		 * PHPAPI: shutdown
212
		 * Queries the FreeSO API to clean shutdown
213
		 * Communicates with external API: Yes
214
		 */
215
		$router->post('/shutdown', function($seconds = false, $subject = false, $message = false) 
216
		{
217
			header('Content-Type: application/json');
218
219
			if(!$seconds) $seconds = 60;
220
221
			if(!$subject || !$message):
222
				return json_encode([
223
					'error_code'    => 'EMPTY_FIELDS',
224
					'error_message' => 'Please enter all fields.'
225
				]);
226
			endif;
227
228
			if(!isset($_SESSION['access_token'])):
229
				return json_encode([
230
					'error_code' => 'NO_AUTH',
231
					'error_message' => 'You have to login first.'
232
				]);
233
			endif;
234
235
			$result = $this->_doPost(
236
				self::API_URL . '/admin/shards/shutdown',
237
				array(
238
					'Content-Type: application/x-www-form-urlencoded',
239
					'Authorization: bearer ' . $_SESSION['access_token'] 
240
				),
241
				array(
242
					'timeout' => $seconds, 
243
					'restart' => true
244
				)
245
			);	
246
247
			$result_ann = $this->_doPost(
248
				self::API_URL . '/admin/shards/announce',
249
				array(
250
					'Content-Type: application/x-www-form-urlencoded',
251
					'Authorization: bearer ' . $_SESSION['access_token'] 
252
				),
253
				array(
254
					'sender'  => $this->_getRandomName(), 
255
					'subject' => $subject, 
256
					'message' => $message
257
				)
258
			);	
259
260
			if($result):
261
				$this->_log($_SERVER['REMOTE_ADDR'] . ' shutdown: ' . $message);
262
				return json_encode(['success' => TRUE]);
263
			endif;
264
265
			return json_encode([
266
				'error_code' => 'BAD_REQUEST',
267
				'error_message' => 'There was a problem with the request.'
268
			]);
269
		});
270
271
		/**
272
		 * PHPAPI: password
273
		 * Changes a user's password
274
		 * Has direct access to database
275
		 * External API needs a new UserApi module
276
		 * Communicates with external API: Yes
277
		 */
278
		$router->post('/password', function($username = false, $password = false) 
279
		{
280
			header('Content-Type: application/json');
281
282
			if(!isset($_SESSION['access_token'])):
283
				return json_encode([
284
					'error_code' => 'NO_AUTH',
285
					'error_message' => 'You have to login first.'
286
				]);
287
			endif;
288
			
289
			if(!$username || !$password):
290
				return json_encode([
291
					'error_code'    => 'EMPTY_FIELDS',
292
					'error_message' => 'Please enter all fields.'
293
				]);
294
			endif;
295
296
			$userModel = new wf_modules\WireframeModel(
297
				'fso_users', $this->_dbh
298
			);
299
300
			if($userModel->load(
301
				'username', $username, 'user_id'
302
			)):
303
				$result = $this->_doPost(
304
					self::API_URL . '/userapi/gethashpassword',
305
					array('Content-Type: application/x-www-form-urlencoded'),
306
					array( 
307
						'password' => $password
308
					)
309
				);
310
311
				if($result):
312
					$result = json_decode($result, TRUE);
313
314
					if($result['password'] != ''):
315
316
						$userAuthModel = new wf_modules\WireframeModel(
317
							'fso_user_authenticate', $this->_dbh
318
						);
319
320
						if($userAuthModel->load(
321
							'user_id', $userModel->user_id, 'data'
322
						)):
323
							$userAuthModel->data = [hex2bin($result['password']), PDO::PARAM_LOB];
324
							$userAuthModel->save('user_id');
325
326
							$this->_log($_SERVER['REMOTE_ADDR'] . ' changed password of ' . $username . ' to *****');
327
							return json_encode([
328
								'success' => TRUE
329
							]);							
330
						endif;
331
					endif;
332
				endif;
333
			endif;
334
335
			return json_encode([
336
				'error_code' => 'NOT_CHANGED',
337
				'error_message' => 'Password was not changed.'
338
			]);			
339
		});
340
341
		/**
342
		 * PHPAPI: budget
343
		 * Increases an avatar's budget
344
		 * Has direct access to database
345
		 * Communicates with external API: No
346
		 */
347
		$router->post('/budget', function($simoleans = false, $avatarName = false) 
348
		{
349
			header('Content-Type: application/json');
350
			
351
			if(!isset($_SESSION['access_token'])):
352
				return json_encode([
353
					'error_code' => 'NO_AUTH',
354
					'error_message' => 'You have to login first.'
355
				]);
356
			endif;
357
358
			if(!$simoleans || !$avatarName):
359
				return json_encode([
360
					'error_code'    => 'EMPTY_FIELDS',
361
					'error_message' => 'Please enter all fields.'
362
				]);
363
			endif;
364
365
			if($simoleans < 0):
366
				return json_encode([
367
					'error_code'    => 'SIMOLEANS_LIMIT',
368
					'error_message' => 'Simoleans cannot be negative.'
369
				]);				
370
			endif;
371
372
			if($simoleans > 50000):
373
				return json_encode([
374
					'error_code'    => 'SIMOLEANS_LIMIT',
375
					'error_message' => 'Can\'t give more than 50k simoleans at a time.'
376
				]);				
377
			endif;
378
379
			if(isset($_SESSION['last_budget_change'])):
380
				$lbc = time() - $_SESSION['last_budget_change'];
381
382
				if($lbc < 60):
383
					$remainder = 60 - $lbc;
384
					return json_encode([
385
						'error_code'    => 'SIMOLEANS_EXHAUST',
386
						'error_message' => 'Please wait ' . $remainder . ' seconds to give simoleans.'
387
					]);
388
				endif;
389
			endif;
390
391
			$avatarModel = new wf_modules\WireframeModel(
392
				'fso_avatars', $this->_dbh
393
			);
394
395
			if($avatarModel->load(
396
				'name', $avatarName, 'budget'
397
			)):
398
				$avatarModel->budget += $simoleans;
399
400
				$avatarModel->save('name');
401
402
				$_SESSION['last_budget_change'] = time();
403
404
				return json_encode([
405
					'success' => TRUE,
406
					'previous_budget' => $avatarModel->budget
407
				]);
408
			endif;
409
410
			return json_encode([
411
				'error_code' => 'NO_AVATAR',
412
				'error_message' => 'Avatar does not exist.'
413
			]);
414
		});
415
416
		/**
417
		 * PHPAPI: globalbudget
418
		 * Increases all avatars' budget
419
		 * Communicates with external API: Yes (to send broadcast)
420
		 */
421
		$router->post('/globalbudget', function($simoleans = false, $message = false) 
422
		{
423
			header('Content-Type: application/json');
424
			
425
			if(!isset($_SESSION['access_token'])):
426
				return json_encode([
427
					'error_code' => 'NO_AUTH',
428
					'error_message' => 'You have to login first.'
429
				]);
430
			endif;
431
432
			if(!$simoleans || !$message):
433
				return json_encode([
434
					'error_code'    => 'EMPTY_FIELDS',
435
					'error_message' => 'Please enter all fields.'
436
				]);
437
			endif;		
438
439
			if($simoleans < 0):
440
				return json_encode([
441
					'error_code'    => 'SIMOLEANS_LIMIT',
442
					'error_message' => 'Simoleans cannot be negative.'
443
				]);				
444
			endif;
445
446
			if($simoleans > 10000):
447
				return json_encode([
448
					'error_code'    => 'SIMOLEANS_LIMIT',
449
					'error_message' => 'Can\'t give more than 10.000$ simoleans at a time.'
450
				]);				
451
			endif;
452
453
			if(isset($_SESSION['last_global_budget_change'])):
454
				$lbc = time() - $_SESSION['last_global_budget_change'];
455
456
				if($lbc < 60):
457
					$remainder = 60 - $lbc;
458
					return json_encode([
459
						'error_code'    => 'SIMOLEANS_EXHAUST',
460
						'error_message' => 'Please wait ' . $remainder . ' seconds to give simoleans.'
461
					]);
462
				endif;
463
			endif;	
464
465
			$this->_dbh->query('UPDATE fso_avatars SET budget = budget + ' . $simoleans)->execute();
466
467
			$result_ann = $this->_doPost(
468
				self::API_URL . '/admin/shards/announce',
469
				array(
470
					'Content-Type: application/x-www-form-urlencoded',
471
					'Authorization: bearer ' . $_SESSION['access_token'] 
472
				),
473
				array(
474
					'sender'  => $this->_getRandomName(), 
475
					'subject' => 'You received ' . $simoleans . '$ simoleans!', 
476
					'message' => $message
477
				)
478
			);	
479
480
			$this->_log($_SERVER['REMOTE_ADDR'] . ' gave global budget (' . $simoleans . '$) to all');
481
482
			$_SESSION['last_global_budget_change'] = time();
483
484
			return json_encode([
485
				'success' => TRUE
486
			]);			
487
		});
488
	}
489
490
	/**
491
	 * _doPost(String $url, $headers[], String $data)
492
	 * Fires a POST request
493
	 */
494
	private function _doPost($url, $headers, $data)
495
	{
496
		$header = '';
497
498
		foreach($headers as $head):
499
			$header .= $head . "\r\n";
500
		endforeach;
501
502
		$options = array(
503
		    'http' => array(
504
		        'header'  => $header,
505
		        'method'  => 'POST',
506
		        'content' => http_build_query($data)
507
		    )
508
		);
509
510
		$context = stream_context_create($options);
511
512
		return file_get_contents($url, false, $context);
513
	}
514
515
	/**
516
	 * _getRandomName()
517
	 * Gets a random TSO name
518
	 */
519
	private function _getRandomName()
520
	{
521
		$names = [
522
			'M.O.M.I. Paula', 
523
			'M.O.M.I. Nick', 
524
			'M.O.M.I. Garry',
525
			'M.O.M.I. Daniel',
526
			'M.O.M.I. James',
527
			'M.O.M.I. Jared',
528
			'M.O.M.I. Elisa',
529
			'M.O.M.I. Marlin',
530
			'M.O.M.I. Harold',
531
			'M.O.M.I. Greg',
532
			'ARIES_OPERATIONS'
533
		];
534
535
		return $names[array_rand($names)];
536
	}
537
}
538
539
return(new FSO_Admin());