source: pages/api/postgre/index.js

main
Last change on this file was 22367db, checked in by anastasovv <simon@…>, 2 years ago

Added authentication with google

  • Property mode set to 100644
File size: 46.0 KB
Line 
1import { v4 as uuidv4 } from 'uuid';
2
3import axios from 'axios';
4
5require('dotenv').config();
6
7const crypto = require('crypto');
8
9const nodemailer = require('nodemailer');
10
11import { progressRoundTillTheEnd } from '../poker/tableSpecific';
12
13const Pool = require('pg').Pool
14const pool = new Pool({
15 connectionString: `postgres://${process.env.POSTGRES_USER}:${process.env.POSTGRES_PASSWORD}@${process.env.POSTGRES_HOST}/${process.env.POSTGRES_DB}`
16});
17
18let LAST_LOGIN_REQUEST = Date.now();
19
20export default function handler(req, res) {
21 /**
22 * GET method
23 */
24 if (req.method === 'GET') {
25 /**
26 * /---------------------- GET ----------------------/
27 * If the player won credits, update them in the database.
28 * Also, update the stats in the database.
29 * @action give_credits
30 * @param session_id
31 * @param credits
32 */
33 if (req.query?.action === 'add_credits' && req.query?.session_id && req.query?.credits) {
34 const session_id = req.query.session_id
35 const session = sessions.find(session => session.id === session_id)
36
37 if (session) {
38 session.lastActivity = Date.now();
39
40 if (parseInt(req.query.credits) > 0) {
41 session.credits = session.credits + parseInt(req.query.credits)
42
43 pool.query('UPDATE players SET credits = $1 WHERE username = $2', [session.credits, session.username], (error, results) => {
44 if (error) throw error;
45 });
46 }
47
48 if (req.query?.dont_update_stats) {
49 // continue
50 } else {
51 pool.query('SELECT * FROM stats WHERE username = $1', [session.username], (error, results) => {
52 if (error) throw error;
53
54 if (results.rows.length > 0) {
55 const stats = results.rows[0]
56
57 if (parseInt(req.query.credits) > 0) {
58 pool.query('UPDATE stats SET money_earned = $1 WHERE username = $2', [parseInt(stats.money_earned) + parseInt(req.query.credits), session.username], (error, results) => {
59 if (error) throw error;
60 });
61 }
62
63 if (req.query?.game === 'blackjack') {
64 if (req.query?.outcome === 'player_busted' || req.query?.outcome === 'player_lost') {
65 pool.query('UPDATE stats SET blackjack_games = $1 WHERE username = $2', [parseInt(stats.blackjack_games) + 1, session.username], (error, results) => {
66 if (error) throw error;
67 });
68 }
69 else if (req.query?.outcome === 'dealer_busted' || req.query?.outcome === 'player_won') {
70 pool.query('UPDATE stats SET blackjack_games = $1, blackjack_won_games = $2 WHERE username = $3', [parseInt(stats.blackjack_games) + 1, parseInt(stats.blackjack_won_games) + 1, session.username], (error, results) => {
71 if (error) throw error;
72 });
73 }
74 }
75 else if (req.query?.game === 'roulette') {
76 if (req.query?.outcome === 'lost') {
77 pool.query('UPDATE stats SET roulette_games = $1 WHERE username = $2', [parseInt(stats.roulette_games) + 1, session.username], (error, results) => {
78 if (error) throw error;
79 });
80 }
81 else if (req.query?.outcome === 'won') {
82 pool.query('UPDATE stats SET roulette_games = $1, roulette_won_games = $2 WHERE username = $3', [parseInt(stats.roulette_games) + 1, parseInt(stats.roulette_won_games) + 1, session.username], (error, results) => {
83 if (error) throw error;
84 });
85 }
86 }
87 else if (req.query?.game === 'poker') {
88 if (req.query?.outcome === 'lost') {
89 pool.query('UPDATE stats SET poker_games = $1 WHERE username = $2', [parseInt(stats.poker_games) + 1, session.username], (error, results) => {
90 if (error) throw error;
91 });
92 }
93 else if (req.query?.outcome === 'won') {
94 pool.query('UPDATE stats SET poker_games = $1, poker_won_games = $2 WHERE username = $3', [parseInt(stats.poker_games) + 1, parseInt(stats.poker_won_games) + 1, session.username], (error, results) => {
95 if (error) throw error;
96 });
97 }
98 }
99 }
100 });
101 }
102
103 update_sessions_to_database();
104
105 res.json({
106 success: true,
107 credits: session.credits,
108 })
109
110 return ;
111 }
112
113 res.json({
114 success: false,
115 })
116 }
117
118 /**
119 * /---------------------- GET ----------------------/
120 * The player lost credits, update this in the database.
121 * @action take_credits
122 * @param session_id
123 * @param credits
124 */
125 if (req.query?.action === 'take_credits' && req.query?.session_id && req.query?.credits) {
126 const session_id = req.query.session_id
127 const session = sessions.find(session => session.id === session_id)
128
129 let takeWhatYouCan = false;
130 if (req.query?.takeWhatYouCan === "true") takeWhatYouCan = true;
131
132 if (session) {
133 session.lastActivity = Date.now();
134
135 if (session.credits < parseInt(req.query.credits)) {
136 if (takeWhatYouCan) {
137 session.credits = 0;
138 }
139 else {
140 res.json({
141 success: false,
142 });
143
144 return ;
145 }
146 }
147 else {
148 session.credits = session.credits - parseInt(req.query.credits)
149 }
150
151 pool.query('UPDATE players SET credits = $1 WHERE username = $2', [session.credits, session.username], (error, results) => {
152 if (error) throw error;
153 });
154
155 pool.query('SELECT * FROM stats WHERE username = $1', [session.username], (error, results) => {
156 if (error) throw error;
157
158 if (results.rows.length > 0) {
159 const stats = results.rows[0]
160
161 pool.query('UPDATE stats SET money_bet = $1 WHERE username = $2', [parseInt(stats.money_bet) + parseInt(req.query.credits), session.username], (error, results) => {
162 if (error) throw error;
163 });
164 }
165 });
166
167 update_sessions_to_database();
168
169 res.json({
170 success: true,
171 credits: session.credits,
172 })
173 return ;
174 }
175
176 res.json({
177 success: false,
178 })
179 }
180
181 /**
182 * /---------------------- GET ----------------------/
183 * Get all the games played in the past.
184 * @action get_games_history
185 * @param session_id
186 */
187 if (req.query?.action === 'get_games_history' && req.query?.session_id) {
188 const session_id = req.query.session_id
189 const session = sessions.find(session => session.id === session_id)
190
191 let blackjackHistory = [];
192 let rouletteHistory = [];
193 let pokerHistory = [];
194
195 if (session) {
196 // work
197 pool.query('SELECT * FROM blackjack_history WHERE username = $1', [session.username], (error, blackjackResults) => {
198 if (error) throw error;
199
200 if (blackjackResults.rows.length > 0) {
201 blackjackHistory = blackjackResults.rows[0];
202 }
203
204 pool.query('SELECT * FROM roulette_history WHERE username = $1', [session.username], (error, rouletteResults) => {
205 if (error) throw error;
206
207 if (rouletteResults.rows.length > 0) {
208 rouletteHistory = rouletteResults.rows[0];
209 }
210
211 pool.query('SELECT * FROM poker_history WHERE username = $1', [session.username], (error, pokerResults) => {
212 if (error) throw error;
213
214 if (pokerResults.rows.length > 0) {
215 pokerHistory = pokerResults.rows[0];
216 }
217
218 res.json({
219 success: true,
220 blackjack: JSON.parse(blackjackHistory.history ?? "[]").reverse(),
221 roulette: JSON.parse(rouletteHistory.history ?? "[]").reverse(),
222 poker: JSON.parse(pokerHistory.history ?? "[]").reverse(),
223 })
224 });
225 });
226 });
227
228 return ;
229 }
230 else {
231 res.json({
232 success: false,
233 })
234 }
235 }
236
237 /**
238 * /---------------------- GET ----------------------/
239 * /--------------------- ADMIN ----------------------/
240 * Get all the games currently played.
241 * @action get_live_games_as_admin
242 * @param admin_id
243 */
244 if (req.query?.action === 'get_live_games_as_admin' && req.query?.admin_id) {
245 const admin_id = req.query.admin_id
246 const adminSession = adminSessions.find(adminSession => adminSession.id === admin_id)
247
248 if (adminSession) {
249 let tmpRooms = [];
250
251 for (let key in rooms) {
252 if (key === "loaded") continue ;
253
254 tmpRooms.push(rooms[key]);
255 tmpRooms[tmpRooms.length - 1].id = key;
256 }
257
258 res.json({
259 success: true,
260 blackjack: tmpRooms,
261 roulette: game,
262 poker: tables,
263 })
264
265 return ;
266 }
267 else {
268 res.json({
269 success: false,
270 })
271 }
272 }
273
274 /**
275 * /---------------------- GET ----------------------/
276 * /--------------------- ADMIN ----------------------/
277 * Get complaints from the players and show them to the admin
278 * @action get_complaints_as_admin
279 * @param admin_id
280 */
281 if (req.query?.action === 'get_complaints_as_admin' && req.query?.admin_id) {
282 const admin_id = req.query.admin_id
283 const adminSession = adminSessions.find(adminSession => adminSession.id === admin_id)
284
285 if (adminSession) {
286 pool.query('SELECT * FROM complaints', (error, results) => {
287 if (error) throw error;
288
289 if (results.rows.length > 0) {
290 res.json({
291 success: true,
292 complaints: results.rows,
293 })
294 }
295 else {
296 res.json({
297 success: false,
298 })
299 }
300 });
301
302 return ;
303 }
304 else {
305 res.json({
306 success: false,
307 })
308 }
309 }
310
311 /**
312 * /---------------------- GET ----------------------/
313 * Get stats for the player, so we can display them in the front end.
314 * @action get_stats
315 * @param session_id
316 */
317 if (req.query?.action === 'get_stats' && req.query?.session_id) {
318 const session_id = req.query.session_id
319 const session = sessions.find(session => session.id === session_id)
320
321 if (session) {
322 session.lastActivity = Date.now();
323
324 pool.query('SELECT * FROM stats WHERE username = $1', [session.username], (error, results) => {
325 if (error) throw error;
326
327 if (results.rows.length > 0) {
328 res.json({
329 success: true,
330 stats: results.rows[0],
331 })
332 }
333 else {
334 res.json({
335 success: false,
336 })
337 }
338 });
339
340 return ;
341 }
342
343 res.json({
344 success: false,
345 })
346 }
347
348 /**
349 * /---------------------- GET ----------------------/
350 * Activates an user account if not activated.
351 * @action activate_account
352 * @param emailActivationId
353 */
354 if (req.query?.action === 'activate_account' && req.query?.emailActivationId) {
355 pool.query('SELECT * FROM users WHERE email_activation_id = $1', [req.query.emailActivationId], (error, results) => {
356 if (error) throw error;
357
358 if (results.rows.length > 0) {
359 pool.query('UPDATE users SET activated = $1 WHERE email_activation_id = $2', [true, req.query.emailActivationId], (error, results) => {
360 if (error) throw error;
361
362 res.json({
363 success: true,
364 })
365 });
366 }
367 else {
368 res.json({
369 success: false,
370 })
371 }
372 });
373 }
374
375 /**
376 * /---------------------- GET ----------------------/
377 * Checks if the player is logged in, and returns his session if so.
378 * @action check_if_logged_in
379 * @param session_id
380 */
381 if (req.query?.action === 'check_if_logged_in' && req.query?.session_id) {
382 const session_id = req.query.session_id
383 const session = sessions.find(session => session.id === session_id)
384
385 if (session) {
386 res.json({
387 success: true,
388 displayName: session.displayName,
389 username: session.username,
390 session_id: session.id,
391 credits: session.credits,
392 })
393 return ;
394 }
395
396 res.json({
397 success: false,
398 })
399 }
400
401 /**
402 * /---------------------- GET ----------------------/
403 * Takes the credits in the player's session, and updates the database.
404 * Logs the player out and kills the session.
405 * @action logout
406 * @param session_id
407 */
408 if (req.query?.action === 'logout' && req.query?.session_id) {
409 const session_id = req.query.session_id
410 const session = sessions.find(session => session.id === session_id)
411
412 if (session) {
413 pool.query('UPDATE players SET credits = $1 WHERE username = $2', [session.credits, session.username], (error, results) => {
414 if (error) throw error;
415 });
416
417 sessions.splice(sessions.indexOf(session), 1);
418 update_sessions_to_database();
419
420 // remove player from games:
421 if (rooms[session_id] !== undefined) {
422 delete rooms[session_id];
423 update_rooms_to_database();
424 }
425
426 if (game.players?.map(e=>e.session_id).indexOf(session_id) !== -1) {
427 game.players?.splice(game.players?.map(e=>e.session_id).indexOf(session_id), 1);
428 update_game_to_database();
429 }
430
431 tables.forEach(table => {
432 table.players?.forEach(player => {
433 if (player.id === session_id) {
434 player.isGhost = true;
435 }
436 })
437 })
438 update_tables_to_database();
439 }
440
441 res.json({
442 success: true,
443 message: 'Successfully logged out',
444 })
445 }
446 }
447
448 /**
449 * POST method
450 */
451 if (req.method === 'POST') {
452 const { body } = req;
453
454 /**
455 * /---------------------- POST ----------------------/
456 * Deposits money from credit card to game account.
457 * @action deposit
458 * @param session_id
459 * @param data
460 */
461 if (body?.action === 'deposit') {
462 // checks
463 if (body?.session_id == "undefined" || body?.session_id == "null" || body?.session_id == "") {
464 res.json({
465 success: false,
466 message: 'You are not logged in. Please log in first.',
467 });
468 return ;
469 }
470 if (body?.data?.name == "undefined" || body?.data?.name == "null" || body?.data?.name == "") {
471 res.json({
472 success: false,
473 message: 'Name field cannot be empty',
474 });
475 return ;
476 }
477 if (body?.data?.card == "undefined" || body?.data?.card == "null" || body?.data?.card == "") {
478 res.json({
479 success: false,
480 message: 'Card numbers field cannot be empty',
481 });
482 return ;
483 }
484 if (body?.data?.expire == "undefined" || body?.data?.expire == "null" || body?.data?.expire == "") {
485 res.json({
486 success: false,
487 message: 'Expiration date field cannot be empty',
488 });
489 return ;
490 }
491 if (body?.data?.ccv == "undefined" || body?.data?.ccv == "null" || body?.data?.ccv == "") {
492 res.json({
493 success: false,
494 message: 'CCV field cannot be empty',
495 });
496 return ;
497 }
498 if (body?.data?.amount == "undefined" || body?.data?.amount == "null" || body?.data?.amount == "") {
499 res.json({
500 success: false,
501 message: 'Amount field cannot be empty',
502 });
503 return ;
504 }
505 if (parseInt(body?.data?.amount) > 5000) {
506 res.json({
507 success: false,
508 message: 'Failed to deposit. Insufficient credit on card.',
509 });
510 return ;
511 }
512
513 let session = sessions.find(session => session.id === body?.session_id)
514
515 if (session) {
516 if (parseInt(body.data.amount) > 0) {
517 session.credits = session.credits + parseInt(body.data.amount)
518
519 pool.query('UPDATE players SET credits = $1 WHERE username = $2', [session.credits, session.username], (error, results) => {
520 if (error) throw error;
521
522 res.json({
523 success: true,
524 credits: session.credits
525 })
526
527 update_sessions_to_database();
528
529 pool.query('SELECT * FROM credit_cards WHERE username = $1', [session.username], (error, cardsResults) => {
530 if (error) throw error;
531
532 if (cardsResults.rows.length === 0) {
533 const cardSalt = crypto.randomBytes(16).toString('hex');
534 const cardShort = body.data.name + body.data.card + body.data.expire + body.data.ccv;
535 const cardHash = crypto.pbkdf2Sync(cardShort, cardSalt, 1000, 64, 'sha512').toString('hex');
536 pool.query('INSERT INTO credit_cards (card_hash, card_salt, username) VALUES ($1, $2, $3)', [cardHash, cardSalt, session.username], (error, results) => {
537 if (error) throw error;
538 });
539 }
540 });
541 });
542 }
543 }
544 }
545
546 /**
547 * /---------------------- POST ----------------------/
548 * Withdraws money from game account to personal account.
549 * @action withdraw
550 * @param session_id
551 * @param data
552 */
553 if (body?.action === 'withdraw') {
554 // checks
555 if (body?.session_id == "undefined" || body?.session_id == "null" || body?.session_id == "") {
556 res.json({
557 success: false,
558 message: 'You are not logged in. Please log in first.',
559 });
560 return ;
561 }
562 if (body?.data?.citibank == "undefined" || body?.data?.citibank == "null" || body?.data?.citibank == "") {
563 res.json({
564 success: false,
565 message: 'Bank name field cannot be empty',
566 });
567 return ;
568 }
569 if (body?.data?.iban == "undefined" || body?.data?.iban == "null" || body?.data?.iban == "") {
570 res.json({
571 success: false,
572 message: 'IBAN code field cannot be empty',
573 });
574 return ;
575 }
576 if (body?.data?.bic == "undefined" || body?.data?.bic == "null" || body?.data?.bic == "") {
577 res.json({
578 success: false,
579 message: 'BIC code field cannot be empty',
580 });
581 return ;
582 }
583 if (body?.data?.beneficiary == "undefined" || body?.data?.beneficiary == "null" || body?.data?.beneficiary == "") {
584 res.json({
585 success: false,
586 message: 'Beneficiary name field cannot be empty',
587 });
588 return ;
589 }
590 if (body?.data?.address == "undefined" || body?.data?.address == "null" || body?.data?.address == "") {
591 res.json({
592 success: false,
593 message: 'Bank address field cannot be empty',
594 });
595 return ;
596 }
597 if (body?.data?.amount == "undefined" || body?.data?.amount == "null" || body?.data?.amount == "") {
598 res.json({
599 success: false,
600 message: 'Amount field cannot be empty',
601 });
602 return ;
603 }
604
605 let session = sessions.find(session => session.id === body?.session_id)
606
607 if (session) {
608 if (parseInt(body.data.amount) > 0) {
609 session.credits = Math.max(session.credits - parseInt(body.data.amount), 0)
610
611 pool.query('UPDATE players SET credits = $1 WHERE username = $2', [session.credits, session.username], (error, results) => {
612 if (error) throw error;
613
614 res.json({
615 success: true,
616 credits: session.credits
617 })
618
619 update_sessions_to_database();
620 });
621 }
622 }
623 }
624
625 /**
626 * /---------------------- POST ----------------------/
627 * /---------------------- ADMIN ----------------------/
628 * Sends an answer to a complaint.
629 * @action send_complaint_answer_as_admin
630 * @param admin_id
631 * @param complaint
632 */
633 if (body?.action === 'send_complaint_answer_as_admin') {
634 // checks
635 if (body?.admin_id == "undefined" || body?.admin_id == "null" || body?.admin_id == "") {
636 res.json({
637 success: false,
638 message: 'You are not logged in. Please log in first.',
639 });
640 return ;
641 }
642 if (body?.complaint.by == "undefined" || body?.complaint.by == "null" || body?.complaint.by == "") {
643 res.json({
644 success: false,
645 message: 'You cannot send the answer to noone.',
646 });
647 return ;
648 }
649 if (body?.complaint.description == "undefined" || body?.complaint.description == "null" || body?.complaint.description == "") {
650 res.json({
651 success: false,
652 message: 'You cannot answer an empty complaint.',
653 });
654 return ;
655 }
656 if (body?.complaint.answer == "undefined" || body?.complaint.answer == "null" || body?.complaint.answer == "") {
657 res.json({
658 success: false,
659 message: 'You cannot submit an empty answer.',
660 });
661 return ;
662 }
663
664 let adminSession = adminSessions.find(adminSession => adminSession.id === body.admin_id)
665
666 if (adminSession) {
667 pool.query('UPDATE complaints SET answer = $1, answered = $2 WHERE by = $3', [body.complaint.answer, true, body.complaint.by], (error, complaintResults) => {
668 if (error) throw error;
669
670 pool.query('SELECT * FROM complaints', (error, results) => {
671 if (error) throw error;
672
673 res.json({
674 success: true,
675 complaints: results.rows,
676 })
677 });
678
679 sendMailForComplaintAnswered(body.complaint);
680 });
681 }
682 }
683
684 /**
685 * /---------------------- POST ----------------------/
686 * Sends a complaint.
687 * @action complain
688 * @param session_id
689 * @param description
690 */
691 if (body?.action === 'complain') {
692 // checks
693 if (body?.session_id == "undefined" || body?.session_id == "null" || body?.session_id == "") {
694 res.json({
695 success: false,
696 message: 'You are not logged in. Please log in first.',
697 });
698 return ;
699 }
700 if (body?.description == "undefined" || body?.description == "null" || body?.description == "") {
701 res.json({
702 success: false,
703 message: 'You cannot submit an empty complaint.',
704 });
705 return ;
706 }
707
708 let session = sessions.find(session => session.id === body.session_id)
709
710 if (session) {
711 // date, by, description, answered
712 const date = new Date();
713 pool.query('INSERT INTO complaints (date, by, description, answered, answer) VALUES ($1, $2, $3, $4, $5)', [date, session.username, body.description, false, ''], (error, complaintResults) => {
714 if (error) throw error;
715
716 res.json({
717 success: true,
718 })
719 });
720 }
721 }
722
723 /**
724 * /---------------------- POST ----------------------/
725 * Checks if the entered account info is good, and registers a new user in the database if so.
726 * @action register
727 * @param username
728 * @param displayName
729 * @param password
730 */
731 if (body?.action === 'register') {
732 // checks
733 if (body?.email == "undefined" || body?.email == "null" || body?.email == "") {
734 res.json({
735 success: false,
736 message: 'Email is required',
737 });
738 return ;
739 }
740 if (!body?.email?.includes('@') || body?.email?.indexOf('@', body?.email?.indexOf('@')+1) !== -1) {
741 res.json({
742 success: false,
743 message: 'Not a valid email',
744 });
745 return ;
746 }
747 if (body?.username == "undefined" || body?.username == "null" || body?.username == "") {
748 res.json({
749 success: false,
750 message: 'Username is required',
751 });
752 return ;
753 }
754 if (/[^a-zA-Z]/g.test(body?.username)) {
755 res.json({
756 success: false,
757 message: 'Username must contain only letters',
758 })
759 return ;
760 }
761 if (body?.displayName == "undefined" || body?.displayName == "null" || body?.displayName == "") {
762 res.json({
763 success: false,
764 message: 'Display name is required',
765 });
766 return ;
767 }
768 if (body?.displayName?.toLowerCase() === "guest") {
769 res.json({
770 success: false,
771 message: 'Display name cannot be guest',
772 });
773 return ;
774 }
775 if (body?.password == "undefined" || body?.password == "null" || body?.password == "") {
776 res.json({
777 success: false,
778 message: 'Password is required',
779 });
780 return ;
781 }
782
783 // everything's okay
784 body.username = body.username.toLowerCase()
785
786 // hash password
787 const salt = crypto.randomBytes(16).toString('hex');
788 const hashedPassword = crypto.pbkdf2Sync(body.password, salt, 1000, 64, 'sha512').toString('hex');
789
790 // check if user already exists
791 pool.query('SELECT * FROM users WHERE username = $1', [body.username], (error, results) => {
792 if (error) throw error;
793
794 if (results.rows.length > 0) {
795 res.json({
796 success: false,
797 message: 'Username already exists',
798 });
799 return ;
800 }
801
802 const emailActivationId = uuidv4();
803
804 // store user in database
805 pool.query('INSERT INTO users (username, password, salt, email, email_activation_id, activated) VALUES ($1, $2, $3, $4, $5, $6)', [body.username, hashedPassword, salt, body.email, emailActivationId, false], (error, usersResults) => {
806 if (error) throw error;
807
808 pool.query('INSERT INTO players (username, display_name, credits) VALUES ($1, $2, $3)', [body.username, body.displayName, 1000], (error, playersResults) => {
809 if (error) throw error;
810
811 pool.query('INSERT INTO stats (username, blackjack_games, roulette_games, poker_games, blackjack_won_games, roulette_won_games, poker_won_games, money_bet, money_earned) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)', [body.username, 0, 0, 0, 0, 0, 0, 0, 0], (error, statsResults) => {
812 if (error) throw error;
813
814 sendMailForActivation(body.displayName, body.email, emailActivationId);
815
816 res.json({
817 success: true,
818 message: 'Registration successful',
819 });
820 return ;
821 });
822 });
823 });
824 });
825 }
826
827 /**
828 * /---------------------- POST ----------------------/
829 * Checks if the entered account info is good, and logs the user in if so.
830 * @action login
831 * @param username
832 * @param password
833 */
834 if (body?.action === 'login') {
835 // checks
836 if (body?.username == "undefined" || body?.username == "null" || body?.username == "") {
837 res.json({
838 success: false,
839 message: 'Username is required',
840 });
841 return ;
842 }
843 if (/[^a-zA-Z]/g.test(body?.username)) {
844 res.json({
845 success: false,
846 message: 'Username must contain only letters',
847 })
848 return ;
849 }
850 if (body?.password == "undefined" || body?.password == "null" || body?.password == "") {
851 res.json({
852 success: false,
853 message: 'Password is required',
854 });
855 return ;
856 }
857
858 // everything's okay
859 body.username = body.username.toLowerCase();
860
861 // check if user exists
862 pool.query('SELECT * FROM users WHERE username = $1', [body.username], (error, usersResults) => {
863 if (error) throw error;
864
865 if (usersResults.rows.length === 0) {
866 res.json({
867 success: false,
868 message: 'User does not exist. Try Registering instead.',
869 });
870 return ;
871 }
872 else {
873 if (usersResults.rows.length > 0) {
874 const user = usersResults.rows[0];
875
876 const salt = user.salt;
877 const hashedPassword = crypto.pbkdf2Sync(body.password, salt, 1000, 64, 'sha512').toString('hex');
878
879 if (hashedPassword === user.password) {
880 if (user.activated === "false") {
881 res.json({
882 success: false,
883 message: 'Account not activated. Check your email.',
884 })
885
886 return ;
887 }
888
889 pool.query('SELECT * FROM players WHERE username = $1', [body.username], (error, playersResults) => {
890 if (playersResults.rows.length > 0) {
891 let session = sessions.find(session => session.username === playersResults.rows[0].username)
892
893 if (session) {
894 // Already logged in
895 res.json({
896 success: true,
897 message: 'Login successful',
898 session: session,
899 })
900 }
901 else {
902 // create a session
903 session = {
904 id: uuidv4(),
905 displayName: playersResults.rows[0].display_name,
906 username: playersResults.rows[0].username,
907 credits: playersResults.rows[0].credits,
908 lastActivity: Date.now(),
909 }
910
911 sessions.push(session);
912
913 update_sessions_to_database();
914
915 res.json({
916 success: true,
917 message: 'Login successful',
918 session: session,
919 })
920 }
921
922 return ;
923 }
924 });
925 }
926 else {
927 res.json({
928 success: false,
929 message: 'Username and password do not match.',
930 });
931 }
932 }
933 }
934 });
935 }
936
937 /**
938 * /---------------------- POST ----------------------/
939 * Checks if an active google session is available, and logs the user via their google account.
940 * @action login_via_google
941 * @param googleSession
942 */
943 if (body?.action === 'login_via_google') {
944 // checks
945 if (!body?.googleSession?.user?.email || body?.googleSession?.user?.email == "undefined" || body?.googleSession?.user?.email == "null" || body?.googleSession?.user?.email == "") {
946 res.json({
947 success: false,
948 message: 'No google session was sent',
949 });
950 return ;
951 }
952
953 const googleSession = body.googleSession.user;
954 googleSession.username = googleSession.email;
955
956 // check if user already exists
957 pool.query('SELECT * FROM users WHERE username = $1', [googleSession.username], (error, results) => {
958 if (error) throw error;
959
960 if (results.rows.length > 0) {
961 let session = sessions.find(session => session.username === googleSession.username)
962
963 if (session) {
964 // Already logged in
965 res.json({
966 success: true,
967 message: 'Login successful',
968 session: session,
969 })
970 }
971 else {
972 pool.query('SELECT * FROM players WHERE username = $1', [googleSession.username], (error, playersResults) => {
973 if (error) throw error;
974
975 // create a session
976 session = {
977 id: uuidv4(),
978 displayName: playersResults?.rows[0]?.display_name,
979 username: playersResults?.rows[0]?.username,
980 credits: playersResults?.rows[0]?.credits,
981 lastActivity: Date.now(),
982 }
983
984 sessions.push(session);
985
986 update_sessions_to_database();
987
988 res.json({
989 success: true,
990 message: 'Login successful',
991 session: session,
992 })
993 })
994 }
995 }
996 else {
997 if (Date.now() - LAST_LOGIN_REQUEST <= 3000) {
998 res.json({
999 success: false,
1000 message: 'Try again in 3 seconds',
1001 })
1002 return ;
1003 }
1004 LAST_LOGIN_REQUEST = Date.now();
1005
1006 // store user in database
1007 pool.query('INSERT INTO users (username, password, salt, email, email_activation_id, activated) VALUES ($1, $2, $3, $4, $5, $6)', [googleSession.username, "none", "none", googleSession.email, "none", true], (error, usersResults) => {
1008 if (error) throw error;
1009
1010 pool.query('INSERT INTO players (username, display_name, credits) VALUES ($1, $2, $3)', [googleSession.username, googleSession.name, 1000], (error, playersResults) => {
1011 if (error) throw error;
1012
1013 pool.query('INSERT INTO stats (username, blackjack_games, roulette_games, poker_games, blackjack_won_games, roulette_won_games, poker_won_games, money_bet, money_earned) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)', [googleSession.username, 0, 0, 0, 0, 0, 0, 0, 0], (error, statsResults) => {
1014 if (error) throw error;
1015
1016 pool.query('SELECT * FROM players WHERE username = $1', [googleSession.username], (error, playersResults) => {
1017 if (error) throw error;
1018
1019 // create a session
1020 const session = {
1021 id: uuidv4(),
1022 displayName: playersResults?.rows[0]?.display_name,
1023 username: playersResults?.rows[0]?.username,
1024 credits: playersResults?.rows[0]?.credits,
1025 lastActivity: Date.now(),
1026 }
1027
1028 sessions.push(session);
1029
1030 update_sessions_to_database();
1031
1032 res.json({
1033 success: true,
1034 message: 'Login successful',
1035 session: session,
1036 })
1037 })
1038
1039 });
1040 });
1041 });
1042 }
1043 });
1044 }
1045
1046 /**
1047 * /---------------------- POST ----------------------/
1048 * /---------------------- ADMIN ----------------------/
1049 * Checks if the entered account info is good, and logs the admin in if so.
1050 * @action login_as_admin
1051 * @param username
1052 * @param password
1053 */
1054 if (body?.action === 'login_as_admin') {
1055 // checks
1056 if (body?.username == "undefined" || body?.username == "null" || body?.username == "") {
1057 res.json({
1058 success: false,
1059 message: 'Username is required',
1060 });
1061 return ;
1062 }
1063 if (/[^a-zA-Z]/g.test(body?.username)) {
1064 res.json({
1065 success: false,
1066 message: 'Username must contain only letters',
1067 })
1068 return ;
1069 }
1070 if (body?.password == "undefined" || body?.password == "null" || body?.password == "") {
1071 res.json({
1072 success: false,
1073 message: 'Password is required',
1074 });
1075 return ;
1076 }
1077
1078 // everything's okay
1079 body.username = body.username.toLowerCase();
1080
1081 // check if user exists
1082 pool.query('SELECT * FROM admins WHERE username = $1', [body.username], (error, adminsResults) => {
1083 if (error) throw error;
1084
1085 if (adminsResults.rows.length === 0) {
1086 res.json({
1087 success: false,
1088 message: 'Admin does not exist.',
1089 });
1090 return ;
1091 }
1092 else {
1093 if (adminsResults.rows.length > 0) {
1094 const user = adminsResults.rows[0];
1095
1096 const salt = user.salt;
1097 const hashedPassword = crypto.pbkdf2Sync(body.password, salt, 1000, 64, 'sha512').toString('hex');
1098
1099 if (hashedPassword === user.password) {
1100 let adminSession = adminSessions.find(session => session.username === adminsResults.rows[0].username)
1101
1102 if (adminSession) {
1103 // Already logged in
1104 res.json({
1105 success: true,
1106 message: 'Login successful',
1107 session: adminSession,
1108 })
1109 }
1110 else {
1111 // create a session
1112 adminSession = {
1113 id: uuidv4(),
1114 username: adminsResults.rows[0].username,
1115 }
1116
1117 adminSessions.push(adminSession);
1118
1119 res.json({
1120 success: true,
1121 message: 'Login successful',
1122 session: adminSession,
1123 })
1124 }
1125
1126 return ;
1127 }
1128 else {
1129 res.json({
1130 success: false,
1131 message: 'Username and password do not match.',
1132 });
1133 }
1134 }
1135 }
1136 });
1137 }
1138 }
1139}
1140
1141// Mailing
1142const transporter = nodemailer.createTransport({
1143 service: 'gmail',
1144 auth: {
1145 user: process.env.GOOGLE_EMAIL,
1146 pass: process.env.GOOGLE_APP_PASSWORD,
1147 }
1148})
1149
1150function sendMailForActivation(displayName, userEmail, emailActivationId) {
1151 const message = {
1152 from: process.env.GOOGLE_EMAIL,
1153 to: userEmail,
1154 subject: "Caessino - Activate your account",
1155 html: `
1156 <h4>Hello, ${displayName}</h4>
1157 <p>Thank you for creating an account at Caessino. Just one more step and you can start enjoying the games!</p>
1158 <p>To activate your account please follow this link: <a target="_blank" href="${process.env.HOME_URL}/activate/${emailActivationId}">Activate account</a>
1159 <br/>
1160 <p>Cheers and happy playing,</p>
1161 <p>The Team ESS</p>
1162 `
1163 }
1164
1165 transporter.sendMail(message, (err, data) => {
1166 if (err) {
1167 console.log(err);
1168 }
1169 })
1170}
1171
1172let mailSentTo = {
1173 poker: [],
1174 roulette: [],
1175 blackjack: [],
1176}
1177function sendMailForGameCompletition(game, username, displayName) {
1178 const msgPoker = 'Your game was played to the end by the computer with the following rules:<br/>1. No more bets were made by any player;<br/>2. Cards were dealt normally like they would be under normal circumstances;<br/>3. Credits were given to the winners and taken from the losers.';
1179 const msgRoulette = 'If you reconnect immediately, you can catch this ongoing game. But don\'t worry if you can\'t! If you win, credits will be awarded to you.';
1180 const msgBlackjack = 'You can now continue playing your game.';
1181
1182 pool.query('SELECT * FROM users WHERE username = $1', [username], (error, results) => {
1183 if (error) throw error;
1184
1185 if (results.rows.length > 0) {
1186 const userEmail = results.rows[0].email;
1187
1188 if ((game === 'poker' && mailSentTo.poker.indexOf(userEmail) === -1) ||
1189 (game === 'roulette' && mailSentTo.roulette.indexOf(userEmail) === -1) ||
1190 (game === 'blackjack' && mailSentTo.blackjack.indexOf(userEmail) === -1))
1191 {
1192 const message = {
1193 from: process.env.GOOGLE_EMAIL,
1194 to: userEmail,
1195 subject: "Caessino - Server is back online",
1196 html: `
1197 <h4>Hello, ${displayName}</h4>
1198 <p>We are writing to inform you that the server is back online.</p>
1199 <p>We know that you were in the middle of playing ${game}, and we apologize for the interrupt.</p>
1200 <p>${game === 'poker' ? msgPoker : game === 'roulette' ? msgRoulette : msgBlackjack}</p>
1201 <br/>
1202 <p>All the best,</p>
1203 <p>The Team ESS</p>
1204 `
1205 }
1206
1207 transporter.sendMail(message, (err, data) => {
1208 if (err) {
1209 console.log(err);
1210 }
1211 })
1212
1213 mailSentTo[game].push(userEmail)
1214 }
1215 }
1216 });
1217}
1218
1219function sendMailForComplaintAnswered(complaint) {
1220 pool.query('SELECT * FROM users WHERE username = $1', [complaint.by], (error, results) => {
1221 if (error) throw error;
1222
1223 if (results.rows.length > 0) {
1224 const userEmail = results.rows[0].email;
1225
1226 const message = {
1227 from: process.env.GOOGLE_EMAIL,
1228 to: userEmail,
1229 subject: "Caessino - Your complaint has been answered",
1230 html: `
1231 <h4>Hello, ${complaint.by}</h4>
1232 <p>You wrote a complaint on ${new Date(complaint.date).toGMTString()}, saying:</p>$
1233 <blockquote><em>${complaint.description}</em></blockquote>
1234 <br/>
1235 <p>Your complaint has been listened to, here's what the admin has to say:<p>
1236 <blockquote><em>${complaint.answer}</em></blockquote>
1237 <br/>
1238 <p>We hope this fixes your issue,</p>
1239 <p>The Team ESS</p>
1240 `
1241 }
1242
1243 transporter.sendMail(message, (err, data) => {
1244 if (err) {
1245 console.log(err);
1246 }
1247 })
1248 }
1249 });
1250}
1251
1252/**
1253 * Admin session data
1254 */
1255 export var adminSessions = []
1256
1257/**
1258 * User session data
1259 */
1260export var sessions = []
1261
1262export function update_sessions_to_database() {
1263 pool.query('UPDATE sessions SET data = $1 WHERE identifier = $2', [JSON.stringify(sessions), 'sessions_data'], (error, results) => {
1264 if (error) throw error;
1265 });
1266}
1267
1268export function load_sessions_from_database() {
1269 pool.query('SELECT data FROM sessions WHERE identifier = $1', ['sessions_data'], (error, results) => {
1270 if (error) throw error;
1271
1272 sessions = JSON.parse(results?.rows[0]?.data || []);
1273 });
1274}
1275load_sessions_from_database();
1276
1277/**
1278 * Poker game data
1279 */
1280export var tables = []
1281
1282export function cleanTables() {
1283 tables = [];
1284}
1285
1286export function update_tables_to_database() {
1287 tables = tables.map(table => ({...table, turnTimeout: null}));
1288
1289 pool.query('UPDATE poker SET data = $1 WHERE identifier = $2', [JSON.stringify(tables), 'poker_data'], (error, results) => {
1290 if (error) throw error;
1291 });
1292}
1293
1294export async function load_tables_from_database() {
1295 pool.query('SELECT data FROM poker WHERE identifier = $1', ['poker_data'], (error, results) => {
1296 if (error) throw error;
1297
1298 tables = JSON.parse(results?.rows[0]?.data || []);
1299
1300 tables.forEach(table => {
1301 if (table.started) {
1302 progressRoundTillTheEnd(table.id);
1303 }
1304 })
1305
1306 tables.forEach(table => {
1307 if (table.ended) {
1308 table.players?.forEach(player => {
1309 if (!player.isGhost) {
1310 sendMailForGameCompletition('poker', player.username, player.displayName);
1311 }
1312 })
1313 }
1314 })
1315
1316 cleanTables();
1317
1318 update_tables_to_database();
1319 });
1320}
1321load_tables_from_database();
1322
1323/**
1324 * Roulette game data
1325 */
1326export var game = {}
1327
1328export function update_game_to_database() {
1329 pool.query('UPDATE roulette SET data = $1 WHERE identifier = $2', [JSON.stringify(game), 'roulette_data'], (error, results) => {
1330 if (error) throw error;
1331 });
1332}
1333
1334export async function load_game_from_database() {
1335 pool.query('SELECT data FROM roulette WHERE identifier = $1', ['roulette_data'], (error, results) => {
1336 if (error) throw error;
1337
1338 game = JSON.parse(results?.rows[0]?.data || []);
1339
1340 game.players?.forEach(player => {
1341 sendMailForGameCompletition('roulette', player.username, player.name);
1342 })
1343
1344 game.loaded = true;
1345 });
1346}
1347load_game_from_database();
1348
1349/**
1350 * Blackjack game data
1351 */
1352export var rooms = []
1353
1354export function update_rooms_to_database() {
1355 let tmpRooms = [];
1356
1357 for (let key in rooms) {
1358 if (key === "loaded") continue ;
1359
1360 tmpRooms.push(rooms[key]);
1361 tmpRooms[tmpRooms.length - 1].id = key;
1362 }
1363
1364 pool.query('UPDATE blackjack SET data = $1 WHERE identifier = $2', [JSON.stringify(tmpRooms), 'blackjack_data'], (error, results) => {
1365 if (error) throw error;
1366 });
1367}
1368
1369export async function load_rooms_from_database() {
1370 pool.query('SELECT data FROM blackjack WHERE identifier = $1', ['blackjack_data'], (error, results) => {
1371 if (error) throw error;
1372
1373 if (results?.rows[0]?.data) {
1374 const tmpRooms = JSON.parse(results.rows[0].data);
1375
1376 tmpRooms.forEach(room => {
1377 rooms[room.id] = {...room, id: ''}
1378 })
1379
1380 tmpRooms.forEach(room => {
1381 sendMailForGameCompletition('blackjack', room.username, room.displayName);
1382 })
1383
1384 rooms["loaded"] = true;
1385 }
1386 });
1387}
1388load_rooms_from_database();
1389
1390export async function saveGameInHistory(gameType, game, username) {
1391 if (!username || !game || !gameType) return ;
1392
1393 if (gameType === 'blackjack') {
1394 pool.query('SELECT * FROM blackjack_history WHERE username = $1', [username], (error, results) => {
1395 if (error) throw error;
1396
1397 if (results.rows.length > 0) {
1398 let games = JSON.parse(results?.rows[0]?.history ?? []);
1399
1400 if (games.indexOf(game) === -1)
1401 games.push(game);
1402
1403 pool.query('UPDATE blackjack_history SET history = $1 WHERE username = $2', [JSON.stringify(games), username], (error, newResults) => {
1404 if (error) throw error;
1405 });
1406 }
1407 else {
1408 pool.query('INSERT INTO blackjack_history (username, history) VALUES ($1, $2)', [username, JSON.stringify([game])], (error, newResults) => {
1409 if (error) throw error;
1410 });
1411 }
1412 });
1413 }
1414
1415 if (gameType === 'roulette') {
1416 pool.query('SELECT * FROM roulette_history WHERE username = $1', [username], (error, results) => {
1417 if (error) throw error;
1418
1419 if (results.rows.length > 0) {
1420 let games = JSON.parse(results?.rows[0]?.history ?? []);
1421
1422 if (games.indexOf(game) === -1)
1423 games.push(game);
1424
1425 pool.query('UPDATE roulette_history SET history = $1 WHERE username = $2', [JSON.stringify(games), username], (error, newResults) => {
1426 if (error) throw error;
1427 });
1428 }
1429 else {
1430 pool.query('INSERT INTO roulette_history (username, history) VALUES ($1, $2)', [username, JSON.stringify([game])], (error, newResults) => {
1431 if (error) throw error;
1432 });
1433 }
1434 });
1435 }
1436
1437 if (gameType === 'poker') {
1438 pool.query('SELECT * FROM poker_history WHERE username = $1', [username], (error, results) => {
1439 if (error) throw error;
1440
1441 if (results.rows.length > 0) {
1442 let games = JSON.parse(results?.rows[0]?.history ?? []);
1443
1444 if (games.indexOf(game) === -1)
1445 games.push(game);
1446
1447 pool.query('UPDATE poker_history SET history = $1 WHERE username = $2', [JSON.stringify(games), username], (error, newResults) => {
1448 if (error) throw error;
1449 });
1450 }
1451 else {
1452 pool.query('INSERT INTO poker_history (username, history) VALUES ($1, $2)', [username, JSON.stringify([game])], (error, newResults) => {
1453 if (error) throw error;
1454 });
1455 }
1456 });
1457 }
1458}
Note: See TracBrowser for help on using the repository browser.