Compare commits
4 commits
bfbd1cbf0a
...
f8b73e38c2
| Author | SHA1 | Date | |
|---|---|---|---|
| f8b73e38c2 | |||
| e963576e46 | |||
| b56aedbca6 | |||
| 7182121423 |
12 changed files with 1016 additions and 95 deletions
8
backend/.eslintrc.js
Normal file
8
backend/.eslintrc.js
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
module.exports = {
|
||||||
|
"extends": ["plugin:@fellow/coffee/recommended"],
|
||||||
|
"plugins": ["@fellow/coffee"],
|
||||||
|
"rules": {
|
||||||
|
"@fellow/coffee/indentation": ["error", { "value": 2 }],
|
||||||
|
"@fellow/coffee/colon-assignment-spacing": "off"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -17,14 +17,12 @@ messages =
|
||||||
|
|
||||||
class FFTCGDB
|
class FFTCGDB
|
||||||
constructor: (filename, truncate) ->
|
constructor: (filename, truncate) ->
|
||||||
@filename = filename
|
@db = new sqlite3.Database filename, (err) =>
|
||||||
|
|
||||||
@db = new sqlite3.Database @filename, (err) =>
|
|
||||||
if err
|
if err
|
||||||
logger.error err.message
|
logger.error err.message
|
||||||
|
|
||||||
else
|
else
|
||||||
logger.info "OK open '#{@filename}'"
|
logger.info "OK opened '#{filename}'"
|
||||||
|
|
||||||
@db.run 'PRAGMA foreign_keys = ON;', (err) =>
|
@db.run 'PRAGMA foreign_keys = ON;', (err) =>
|
||||||
logger.error err.message if err
|
logger.error err.message if err
|
||||||
|
|
@ -56,26 +54,44 @@ class FFTCGDB
|
||||||
''', (err) =>
|
''', (err) =>
|
||||||
logger.error err.message if err
|
logger.error err.message if err
|
||||||
|
|
||||||
@db.run '''INSERT INTO users VALUES(1,'jmm','$2b$13$jgDdHHDWqq1RV6PXxf7aOO6AbxqY6tbxIADyIO0FeXt2BlKQCCMzS',NULL);'''
|
@db.run '''
|
||||||
@db.run '''INSERT INTO decks VALUES(1,1,'{"name":"Antipode Bomb Version 6.0","note":"As Seen In Tournament: The North American Water Cup","cards":[{"count":1,"serial":"1-192"},{"count":2,"serial":"7-132"},{"count":2,"serial":"8-037"},{"count":2,"serial":"8-139"},{"count":1,"serial":"5-036"},{"count":3,"serial":"4-048"},{"count":1,"serial":"2-026"},{"count":3,"serial":"8-043"},{"count":3,"serial":"4-021"},{"count":3,"serial":"3-033"},{"count":1,"serial":"8-014"},{"count":2,"serial":"8-006"},{"count":1,"serial":"8-042"},{"count":1,"serial":"6-027"},{"count":3,"serial":"5-019"},{"count":2,"serial":"2-019"},{"count":2,"serial":"5-032"},{"count":3,"serial":"4-026"},{"count":3,"serial":"1-057"},{"count":1,"serial":"1-048"},{"count":2,"serial":"8-036"},{"count":3,"serial":"8-005"},{"count":3,"serial":"2-005"},{"count":1,"serial":"7-017"},{"count":1,"serial":"8-007"}]}');'''
|
INSERT INTO users VALUES (1,'jmm','$2b$13$jgDdHHDWqq1RV6PXxf7aOO6AbxqY6tbxIADyIO0FeXt2BlKQCCMzS',NULL);
|
||||||
|
'''
|
||||||
|
@db.run '''
|
||||||
|
INSERT INTO decks VALUES (1,1,'{
|
||||||
|
"name":"Antipode Bomb Version 6.0",
|
||||||
|
"note":"As Seen In Tournament: The North American Water Cup",
|
||||||
|
"cards":[
|
||||||
|
{"count":1,"serial":"1-192"},{"count":2,"serial":"7-132"},{"count":2,"serial":"8-037"},
|
||||||
|
{"count":2,"serial":"8-139"},{"count":1,"serial":"5-036"},{"count":3,"serial":"4-048"},
|
||||||
|
{"count":1,"serial":"2-026"},{"count":3,"serial":"8-043"},{"count":3,"serial":"4-021"},
|
||||||
|
{"count":3,"serial":"3-033"},{"count":1,"serial":"8-014"},{"count":2,"serial":"8-006"},
|
||||||
|
{"count":1,"serial":"8-042"},{"count":1,"serial":"6-027"},{"count":3,"serial":"5-019"},
|
||||||
|
{"count":2,"serial":"2-019"},{"count":2,"serial":"5-032"},{"count":3,"serial":"4-026"},
|
||||||
|
{"count":3,"serial":"1-057"},{"count":1,"serial":"1-048"},{"count":2,"serial":"8-036"},
|
||||||
|
{"count":3,"serial":"8-005"},{"count":3,"serial":"2-005"},{"count":1,"serial":"7-017"},
|
||||||
|
{"count":1,"serial":"8-007"}
|
||||||
|
]
|
||||||
|
}');
|
||||||
|
'''
|
||||||
|
|
||||||
logger.info 'OK clear'
|
logger.info 'OK clear'
|
||||||
|
|
||||||
close: ->
|
close: ->
|
||||||
logger.info 'shutting down'
|
logger.debug 'shutting down'
|
||||||
new Promise (resolve, reject) =>
|
new Promise (resolve, reject) =>
|
||||||
@db.close (err) ->
|
@db.close (err) ->
|
||||||
if err
|
if err
|
||||||
logger.error "FAIL '#{err.message}'"
|
logger.error "FAIL '#{err.message}'"
|
||||||
reject null
|
reject null
|
||||||
else
|
else
|
||||||
logger.warn "OK close '#{@filename}'"
|
logger.info "OK closed"
|
||||||
resolve null
|
resolve null
|
||||||
|
|
||||||
validate: (login, password) ->
|
validate: (login, password) ->
|
||||||
defined = (value) -> value? and value isnt ''
|
defined = (value) -> value? and value isnt ''
|
||||||
|
|
||||||
new Promise (resolve, reject) =>
|
new Promise (resolve, reject) ->
|
||||||
if (defined login) and (defined password)
|
if (defined login) and (defined password)
|
||||||
# both are defined
|
# both are defined
|
||||||
resolve null
|
resolve null
|
||||||
|
|
@ -97,7 +113,10 @@ class FFTCGDB
|
||||||
|
|
||||||
else
|
else
|
||||||
# try creating row in users table
|
# try creating row in users table
|
||||||
stmt = @db.prepare 'INSERT INTO users (login, pwdhash) VALUES (?, ?)'
|
stmt = @db.prepare '''
|
||||||
|
INSERT INTO users (login, pwdhash)
|
||||||
|
VALUES (?, ?)
|
||||||
|
'''
|
||||||
stmt.run [login, hash], (err) ->
|
stmt.run [login, hash], (err) ->
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
if err
|
if err
|
||||||
|
|
@ -119,8 +138,12 @@ class FFTCGDB
|
||||||
@validate login, password
|
@validate login, password
|
||||||
.then =>
|
.then =>
|
||||||
# get users table row
|
# get users table row
|
||||||
stmt = @db.prepare 'SELECT * FROM users WHERE login = ?'
|
stmt = @db.prepare '''
|
||||||
stmt.get [login], (err, row) =>
|
SELECT *
|
||||||
|
FROM users
|
||||||
|
WHERE login = ?
|
||||||
|
'''
|
||||||
|
stmt.get [login], (err, row) ->
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
if err
|
if err
|
||||||
logger.warn "login: FAIL db '#{err.code}' for '#{login}'"
|
logger.warn "login: FAIL db '#{err.code}' for '#{login}'"
|
||||||
|
|
@ -153,8 +176,12 @@ class FFTCGDB
|
||||||
getUser: (userID) ->
|
getUser: (userID) ->
|
||||||
new Promise (resolve, reject) =>
|
new Promise (resolve, reject) =>
|
||||||
# get users table row
|
# get users table row
|
||||||
stmt = @db.prepare 'SELECT * FROM users WHERE user = ?'
|
stmt = @db.prepare '''
|
||||||
stmt.get [userID], (err, row) =>
|
SELECT *
|
||||||
|
FROM users
|
||||||
|
WHERE user = ?
|
||||||
|
'''
|
||||||
|
stmt.get [userID], (err, row) ->
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
if err
|
if err
|
||||||
logger.warn "get: FAIL db '#{err.code}' for '#{userID}'"
|
logger.warn "get: FAIL db '#{err.code}' for '#{userID}'"
|
||||||
|
|
@ -173,25 +200,35 @@ class FFTCGDB
|
||||||
addDeck: (userID, deckCards) ->
|
addDeck: (userID, deckCards) ->
|
||||||
new Promise (resolve, reject) =>
|
new Promise (resolve, reject) =>
|
||||||
# try creating row in decks table
|
# try creating row in decks table
|
||||||
stmt = @db.prepare 'INSERT INTO decks (user, json) VALUES (?, ?)'
|
stmt = @db.prepare '''
|
||||||
stmt.run [userID, JSON.stringify deckCards], (err) ->
|
INSERT INTO decks (user, json)
|
||||||
|
VALUES (?, ?)
|
||||||
|
'''
|
||||||
|
stmt.run [userID, (JSON.stringify deckCards)], (err) ->
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
if err
|
if err
|
||||||
logger.warn "addDeck: FAIL db '#{err.code}' for '#{userID}'"
|
logger.warn "addDeck: FAIL db '#{err.code}' for '#{userID}'"
|
||||||
reject messages.db
|
reject messages.db
|
||||||
|
|
||||||
else
|
else
|
||||||
|
# eslint-disable-next-line @fellow/coffee/missing-fat-arrows
|
||||||
logger.debug "addDeck: OK '#{@lastID}'"
|
logger.debug "addDeck: OK '#{@lastID}'"
|
||||||
resolve @lastID
|
resolve @lastID
|
||||||
|
|
||||||
modDeck: (userID, deckID, deckCards) ->
|
modDeck: (userID, deckID, deckCards) ->
|
||||||
new Promise (resolve, reject) =>
|
new Promise (resolve, reject) =>
|
||||||
stmt = @db.prepare 'UPDATE decks SET json = ? WHERE deck = ? AND user = ?'
|
stmt = @db.prepare '''
|
||||||
|
UPDATE decks
|
||||||
|
SET json = ?
|
||||||
|
WHERE deck = ? AND user = ?
|
||||||
|
'''
|
||||||
stmt.run [(JSON.stringify deckCards), deckID, userID], (err) ->
|
stmt.run [(JSON.stringify deckCards), deckID, userID], (err) ->
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
|
isUnchanged =
|
||||||
if err
|
if err
|
||||||
logger.warn "modDeck: FAIL db '#{err.code}' for '#{deckID}'"
|
logger.warn "modDeck: FAIL db '#{err.code}' for '#{deckID}'"
|
||||||
reject messages.db
|
reject messages.db
|
||||||
|
# eslint-disable-next-line
|
||||||
else if @changes == 0
|
else if @changes == 0
|
||||||
logger.warn "no changes for input (#{userID}, #{deckID}, #{JSON.stringify deckCards})!"
|
logger.warn "no changes for input (#{userID}, #{deckID}, #{JSON.stringify deckCards})!"
|
||||||
reject messages.db
|
reject messages.db
|
||||||
|
|
@ -200,7 +237,12 @@ class FFTCGDB
|
||||||
|
|
||||||
getDecks: (userID) ->
|
getDecks: (userID) ->
|
||||||
new Promise (resolve, reject) =>
|
new Promise (resolve, reject) =>
|
||||||
stmt = @db.prepare 'SELECT decks.deck, decks.json FROM decks INNER JOIN users ON decks.user = users.user WHERE users.user = ?'
|
stmt = @db.prepare '''
|
||||||
|
SELECT decks.deck, decks.json
|
||||||
|
FROM decks
|
||||||
|
INNER JOIN users ON decks.user = users.user
|
||||||
|
WHERE users.user = ?
|
||||||
|
'''
|
||||||
stmt.all [userID], (err, rows) ->
|
stmt.all [userID], (err, rows) ->
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
if err
|
if err
|
||||||
|
|
@ -212,7 +254,10 @@ class FFTCGDB
|
||||||
|
|
||||||
delDeck: (userID, deckID) ->
|
delDeck: (userID, deckID) ->
|
||||||
new Promise (resolve, reject) =>
|
new Promise (resolve, reject) =>
|
||||||
stmt = @db.prepare 'DELETE FROM decks WHERE deck = ? AND user = ?'
|
stmt = @db.prepare '''
|
||||||
|
DELETE FROM decks
|
||||||
|
WHERE deck = ? AND user = ?
|
||||||
|
'''
|
||||||
stmt.run [deckID, userID], (err) ->
|
stmt.run [deckID, userID], (err) ->
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
if err
|
if err
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,13 @@
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "coffee server.coffee",
|
"start": "coffee server.coffee",
|
||||||
"dev": "nodemon",
|
"dev": "nodemon server.coffee --exec 'yarn lint && yarn start'",
|
||||||
|
"lint": "eslint $(find . -name node_modules -prune -o \\( -type f -iname '*.coffee' -print \\))",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@fellow/eslint-plugin-coffee": "^0.4.13",
|
||||||
|
"eslint": "^5.16.0",
|
||||||
"nodemon": "^1.19.0"
|
"nodemon": "^1.19.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
||||||
26
backend/routes/games/list.coffee
Normal file
26
backend/routes/games/list.coffee
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
logger = (require 'logging').default '/games/list'
|
||||||
|
|
||||||
|
# session storage (volatile data)
|
||||||
|
session = (require '../../session')
|
||||||
|
|
||||||
|
module.exports =
|
||||||
|
url: '/games/list'
|
||||||
|
method: 'POST'
|
||||||
|
# schema: (require './info.schema')
|
||||||
|
|
||||||
|
handler: (request, reply) ->
|
||||||
|
session.check request.body.session ? ""
|
||||||
|
.then (userid) ->
|
||||||
|
# active session found, get associated user
|
||||||
|
session.getGames()
|
||||||
|
.then (games) ->
|
||||||
|
logger.debug "OK '#{userid}' got games"
|
||||||
|
reply.send
|
||||||
|
success: true
|
||||||
|
games: games
|
||||||
|
|
||||||
|
.catch ->
|
||||||
|
# no session found
|
||||||
|
logger.info "FAIL '#{request.body.session}' session not found"
|
||||||
|
reply.send
|
||||||
|
success: false
|
||||||
|
|
@ -28,6 +28,8 @@ fastify.route (require "./routes/#{route}") for route in [
|
||||||
'decks/modify'
|
'decks/modify'
|
||||||
# delete deck
|
# delete deck
|
||||||
'decks/delete'
|
'decks/delete'
|
||||||
|
# list games
|
||||||
|
'games/list'
|
||||||
]
|
]
|
||||||
|
|
||||||
# request logging
|
# request logging
|
||||||
|
|
@ -53,7 +55,11 @@ fastify.listen 3001, '0.0.0.0'
|
||||||
logger.error err
|
logger.error err
|
||||||
|
|
||||||
# Handle termination
|
# Handle termination
|
||||||
process.on 'SIGINT', ->
|
process.on 'SIGUSR2', ->
|
||||||
socket.close()
|
(require './db').close()
|
||||||
logger.info 'shutting down after SIGINT'
|
.then ->
|
||||||
|
logger.info 'shutting down normally after SIGINT'
|
||||||
|
.catch ->
|
||||||
|
logger.info 'error shutting down after SIGINT'
|
||||||
|
.finally ->
|
||||||
process.exit()
|
process.exit()
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ EXPIRY =
|
||||||
|
|
||||||
class FFTCGSESSION
|
class FFTCGSESSION
|
||||||
constructor: ->
|
constructor: ->
|
||||||
@db = redis.createClient
|
@redis = redis.createClient
|
||||||
host: 'redis'
|
host: 'redis'
|
||||||
port: 6379
|
port: 6379
|
||||||
|
|
||||||
@db.on 'error', (err) =>
|
@redis.on 'error', (err) ->
|
||||||
logger.error err.message
|
logger.error err.message
|
||||||
|
|
||||||
sessionKey: (digest) -> "session.#{digest}"
|
sessionKey: (digest) -> "session.#{digest}"
|
||||||
|
|
@ -31,7 +31,7 @@ class FFTCGSESSION
|
||||||
digest = hmac.digest 'base64'
|
digest = hmac.digest 'base64'
|
||||||
|
|
||||||
# push (hash, userid) into DB for the configured timespan
|
# push (hash, userid) into DB for the configured timespan
|
||||||
@db.setex (@sessionKey digest), EXPIRY.login * 86400, userid, =>
|
@redis.setex (@sessionKey digest), EXPIRY.login * 86400, userid, =>
|
||||||
logger.info "OK '#{@sessionKey digest}' created"
|
logger.info "OK '#{@sessionKey digest}' created"
|
||||||
# return cookie data
|
# return cookie data
|
||||||
resolve
|
resolve
|
||||||
|
|
@ -42,7 +42,7 @@ class FFTCGSESSION
|
||||||
destroy: (digest) ->
|
destroy: (digest) ->
|
||||||
new Promise (resolve, reject) =>
|
new Promise (resolve, reject) =>
|
||||||
# delete hash immediately
|
# delete hash immediately
|
||||||
@db.del (@sessionKey digest), (err, res) =>
|
@redis.del (@sessionKey digest), (err, res) =>
|
||||||
if res == 0
|
if res == 0
|
||||||
reject null
|
reject null
|
||||||
else
|
else
|
||||||
|
|
@ -52,12 +52,12 @@ class FFTCGSESSION
|
||||||
check: (digest) ->
|
check: (digest) ->
|
||||||
new Promise (resolve, reject) =>
|
new Promise (resolve, reject) =>
|
||||||
# refresh expiry timer on digest
|
# refresh expiry timer on digest
|
||||||
@db.expire (@sessionKey digest), EXPIRY.login * 86400, (err, res) =>
|
@redis.expire (@sessionKey digest), EXPIRY.login * 86400, (err, res) =>
|
||||||
if res == 0
|
if res == 0
|
||||||
reject null
|
reject null
|
||||||
|
|
||||||
else
|
else
|
||||||
@db.get (@sessionKey digest), (err, res) =>
|
@redis.get (@sessionKey digest), (err, res) =>
|
||||||
logger.debug "OK '#{@sessionKey digest}' resumed"
|
logger.debug "OK '#{@sessionKey digest}' resumed"
|
||||||
resolve res
|
resolve res
|
||||||
|
|
||||||
|
|
@ -69,25 +69,26 @@ class FFTCGSESSION
|
||||||
digest = hmac.digest 'base64'
|
digest = hmac.digest 'base64'
|
||||||
|
|
||||||
# insert game key
|
# insert game key
|
||||||
@db.hsetnx (@gameKey digest), 'owner', userid, (err, res) =>
|
@redis.hsetnx (@gameKey digest), 'owner', userid, (err, res) =>
|
||||||
if res == 0
|
if res == 0
|
||||||
@db.del (@gameKey digest)
|
@redis.del (@gameKey digest)
|
||||||
reject null
|
reject null
|
||||||
|
|
||||||
else
|
else
|
||||||
@db.expire (@gameKey digest), EXPIRY.game * 86400, (err, res) =>
|
@redis.expire (@gameKey digest), EXPIRY.game * 86400, (err, res) =>
|
||||||
if res == 0
|
if res == 0
|
||||||
@db.del (@gameKey digest)
|
@redis.del (@gameKey digest)
|
||||||
reject null
|
reject null
|
||||||
|
|
||||||
else
|
else
|
||||||
# add game to active set
|
# add game to active set
|
||||||
@db.sadd (@gameKey 'active'), (@gameKey digest), (err, res) =>
|
@redis.sadd (@gameKey 'active'), (@gameKey digest), (err, res) =>
|
||||||
# return game ID
|
# return game ID
|
||||||
logger.info "OK '#{@gameKey digest}' created"
|
logger.info "OK '#{@gameKey digest}' created"
|
||||||
resolve digest
|
resolve digest
|
||||||
|
|
||||||
getGames: ->
|
getGames: ->
|
||||||
|
new Promise (resolve) =>
|
||||||
# function to return all active gameKeys
|
# function to return all active gameKeys
|
||||||
activeGameKeys = (set, cursor) =>
|
activeGameKeys = (set, cursor) =>
|
||||||
# start iteration
|
# start iteration
|
||||||
|
|
@ -96,7 +97,9 @@ class FFTCGSESSION
|
||||||
|
|
||||||
return new Promise (resolve, reject) =>
|
return new Promise (resolve, reject) =>
|
||||||
# scan "active" gameKey
|
# scan "active" gameKey
|
||||||
@db.sscan (@gameKey 'active'), cursor, 'COUNT', '100', (err, res) =>
|
@redis.sscan (@gameKey 'active'), cursor, 'COUNT', '100', (err, res) ->
|
||||||
|
if err
|
||||||
|
reject null
|
||||||
|
|
||||||
# add to results set
|
# add to results set
|
||||||
cursor = res[0]
|
cursor = res[0]
|
||||||
|
|
@ -109,22 +112,36 @@ class FFTCGSESSION
|
||||||
else
|
else
|
||||||
# recursive call (resolve one step deeper)
|
# recursive call (resolve one step deeper)
|
||||||
allGames set, cursor
|
allGames set, cursor
|
||||||
.then (set) =>
|
.then (set) ->
|
||||||
resolve set
|
resolve set
|
||||||
|
|
||||||
activeGameKeys().then (set) =>
|
activeGameKeys()
|
||||||
logger.info "game count: #{Array.from(set).length}"
|
.then (set) =>
|
||||||
|
activeGames = []
|
||||||
|
|
||||||
|
for key in Array.from set
|
||||||
|
activeGames.push new Promise (resolve) =>
|
||||||
|
@redis.hget key, 'owner', (err, res) ->
|
||||||
|
if(err)
|
||||||
|
resolve null
|
||||||
|
|
||||||
|
resolve res
|
||||||
|
|
||||||
|
Promise.all activeGames
|
||||||
|
.then (activeGames) ->
|
||||||
|
resolve activeGames
|
||||||
|
|
||||||
|
|
||||||
joinGame: (digest, userid) ->
|
joinGame: (digest, userid) ->
|
||||||
new Promise (resolve, reject) =>
|
new Promise (resolve, reject) =>
|
||||||
# refresh expiry timer on digest
|
# refresh expiry timer on digest
|
||||||
@db.expire (@gameKey digest), EXPIRY.game * 86400, (err, res) =>
|
@redis.expire (@gameKey digest), EXPIRY.game * 86400, (err, res) =>
|
||||||
if res == 0
|
if res == 0
|
||||||
reject null
|
reject null
|
||||||
|
|
||||||
else
|
else
|
||||||
# insert opponent value
|
# insert opponent value
|
||||||
@db.hsetnx (@gameKey digest), 'opponent', userid, (err, res) =>
|
@redis.hsetnx (@gameKey digest), 'opponent', userid, (err, res) =>
|
||||||
if res == 0
|
if res == 0
|
||||||
reject null
|
reject null
|
||||||
|
|
||||||
|
|
@ -136,13 +153,13 @@ class FFTCGSESSION
|
||||||
updateGame: (digest, state) ->
|
updateGame: (digest, state) ->
|
||||||
new Promise (resolve, reject) =>
|
new Promise (resolve, reject) =>
|
||||||
# refresh expiry timer on digest
|
# refresh expiry timer on digest
|
||||||
@db.expire (@gameKey digest), EXPIRY.game * 86400, (err, res) =>
|
@redis.expire (@gameKey digest), EXPIRY.game * 86400, (err, res) =>
|
||||||
if res == 0
|
if res == 0
|
||||||
reject null
|
reject null
|
||||||
|
|
||||||
else
|
else
|
||||||
# update state value
|
# update state value
|
||||||
@db.hset (@gameKey digest), 'state', (JSON.stringify state), (err, res) =>
|
@redis.hset (@gameKey digest), 'state', (JSON.stringify state), (err, res) =>
|
||||||
if res == 0
|
if res == 0
|
||||||
reject null
|
reject null
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -3,7 +3,7 @@
|
||||||
{
|
{
|
||||||
"id": "SdPO5j8y6",
|
"id": "SdPO5j8y6",
|
||||||
"path": "/app",
|
"path": "/app",
|
||||||
"favorite": 0,
|
"favorite": 1,
|
||||||
"type": "vue",
|
"type": "vue",
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"openDate": 1557166583987,
|
"openDate": 1557166583987,
|
||||||
|
|
|
||||||
36
frontend/src/components/GamesList.vue
Normal file
36
frontend/src/components/GamesList.vue
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div v-for="game in games" :key="game">
|
||||||
|
{{ game }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from '@/plugins/axios'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'GamesList',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
session: String
|
||||||
|
},
|
||||||
|
|
||||||
|
asyncComputed: {
|
||||||
|
games: {
|
||||||
|
get() {
|
||||||
|
return axios
|
||||||
|
.post('/games/list', {
|
||||||
|
session: this.session
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.data.success) {
|
||||||
|
return response.data.games
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
default: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -4,7 +4,9 @@
|
||||||
<v-icon>view_carousel</v-icon> Decks
|
<v-icon>view_carousel</v-icon> Decks
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-btn flat> <v-icon>play_arrow</v-icon> Play </v-btn>
|
<v-btn flat :to="{ name: 'games' }">
|
||||||
|
<v-icon>play_arrow</v-icon> Play
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
<v-btn flat :to="{ name: 'usercp' }">
|
<v-btn flat :to="{ name: 'usercp' }">
|
||||||
<v-icon>person</v-icon> {{ user.login }}
|
<v-icon>person</v-icon> {{ user.login }}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,12 @@ export default new Router({
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "deckcp" */ './views/DeckCP.vue')
|
import(/* webpackChunkName: "deckcp" */ './views/DeckCP.vue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/games',
|
||||||
|
name: 'games',
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "games" */ './views/Games.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/game',
|
path: '/game',
|
||||||
name: 'game',
|
name: 'game',
|
||||||
|
|
|
||||||
29
frontend/src/views/Games.vue
Normal file
29
frontend/src/views/Games.vue
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<v-content>
|
||||||
|
<HeaderIntern v-model="session" @user="user = $event" />
|
||||||
|
|
||||||
|
<v-container v-if="user">
|
||||||
|
<h2 class="headline">Open Tables</h2>
|
||||||
|
<GamesList :session="session" />
|
||||||
|
</v-container>
|
||||||
|
</v-content>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import HeaderIntern from '@/components/HeaderIntern.vue'
|
||||||
|
import GamesList from '@/components/GamesList.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Games',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
HeaderIntern,
|
||||||
|
GamesList
|
||||||
|
},
|
||||||
|
|
||||||
|
data: () => ({
|
||||||
|
session: null,
|
||||||
|
user: null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Reference in a new issue